packages feed

web3 0.7.3.0 → 0.8.0.0

raw patch · 107 files changed

+14193/−3344 lines, 107 filesdep +OneTupledep +containersdep +microlensdep ~aesondep ~basedep ~basement

Dependencies added: OneTuple, containers, microlens, microlens-aeson, microlens-mtl, microlens-th, random, relapse, secp256k1-haskell, vinyl

Dependency ranges changed: aeson, base, basement, bytestring, cereal, cryptonite, generics-sop, hspec, hspec-discover, http-client, http-client-tls, memory, mtl, parsec, split, stm, template-haskell, text, time

Files

CHANGELOG.md view
@@ -1,6 +1,33 @@ # Changelog All notable changes to this project will be documented in this file. +## [0.8.0.0] 2018-10-**+### Added+- Support for Ethereum cryptography+- Local private key transaction signer +- Generalized JSON-RPC monad for API methods+- Support for multiple transaction sending methods via one `Account` api+- Monad based transaction sending parametrization +- Experimental support for solidity compiler (disabled by default) +- Support for Ethereum mainnet ENS resolver+- Contract typeclass with api/bytecode getters+- Contract typeclass TH generator+- Function for creating contracts+- Event single/multi filters+- HexString data type+- Personal api calls+- Address checksum++### Changed+- package.yaml instead web3.cabal package descriptor+- Solidity related data types and codecs moved to Data.Solidity+- Solidity related parsers and compiler moved to Language.Solidity+- Modules in Network.Ethereum.Web3 moved to Network.Ethereum.Api+- fromWei/toWei from `Unit` typeclass now operates over `Integral`++### Removed+- `convert` function from `Unit` typeclass+ ## [0.7.3.0] 2018-05-22 ### Added - 'Network.Ethereum.ABI.Prim' meta-module as primitive types and instances aggregator.
LICENSE view
@@ -1,4 +1,4 @@-Copyright Alexander Krupenkin (c) 2016+Copyright Alexander Krupenkin (c) 2016-2018  All rights reserved. 
README.md view
@@ -1,76 +1,79 @@-## Ethereum Haskell API+Ethereum API for Haskell+======================== -This is the Ethereum compatible Haskell API which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) spec.+The Haskell Ethereum API which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC). +[![Documentation Status](https://readthedocs.org/projects/hs-web3/badge/?version=latest)](https://hs-web3.readthedocs.io/en/latest/?badge=latest) [![Build Status](https://travis-ci.org/airalab/hs-web3.svg?branch=master)](https://travis-ci.org/airalab/hs-web3)-[![Build status](https://ci.appveyor.com/api/projects/status/8ljq93nar8kobk75?svg=true)](https://ci.appveyor.com/project/akru/hs-web3) [![Hackage](https://img.shields.io/hackage/v/web3.svg)](http://hackage.haskell.org/package/web3)-![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)+[![LTS-12](http://stackage.org/package/web3/badge/lts-12)](http://stackage.org/lts-12/package/web3)+[![nightly](http://stackage.org/package/web3/badge/nightly)](http://stackage.org/nightly/package/web3)+[![Code Triagers](https://www.codetriage.com/airalab/hs-web3/badges/users.svg)](https://www.codetriage.com/airalab/hs-web3) ![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)-[![Code Triagers Badge](https://www.codetriage.com/airalab/hs-web3/badges/users.svg)](https://www.codetriage.com/airalab/hs-web3) -### Installation+Install+------- -    $ git clone https://github.com/airalab/hs-web3 && cd hs-web3-    $ stack setup-    $ stack ghci+`stack install web3` -> This library runs only paired with [geth](https://github.com/ethereum/go-ethereum)-> or [parity](https://github.com/ethcore/parity) Ethereum node,-> please start node first before using the library.+Usage+----- -### Web3 monad+```haskell+{-# LANGUAGE OverloadedStrings #-}+module Main where -Any Ethereum node communication wrapped with `Web3` monadic type.+-- Basic imports+import           Network.Ethereum.Web3 -    > import Network.Ethereum.Web3.Web3-    > :t clientVersion-    clientVersion :: Web3 Text+-- Eth API support+import qualified Network.Ethereum.Api.Eth   as Eth+import           Network.Ethereum.Api.Types -To run this computation used `runWeb3'` or `runWeb3` functions.+-- ENS support+import qualified Network.Ethereum.Ens       as Ens -    > import Network.Ethereum.Web3-    > runWeb3 clientVersion-    Right "Parity//v1.4.5-beta-a028d04-20161126/x86_64-linux-gnu/rustc1.13.0"+-- Lens to simple param setting+import           Lens.Micro                 ((.~)) -Function `runWeb3` use default `Web3` provider at `localhost:8545`.+main :: IO ()+main = do+    -- Use default provider on http://localhost:8545+    ret <- runWeb3 $ do -    > :t runWeb3-    runWeb3-      :: MonadIO m => Web3 a -> m (Either Web3Error a)+        -- Get address of default account+        me <- head <$> Eth.accounts -### TemplateHaskell generator+        -- Get balance of default account on latest block+        myBalance <- Eth.getBalance me Latest -[Quasiquotation](https://wiki.haskell.org/Quasiquotation) is used to parse contract ABI or load from JSON file. [TemplateHaskell](https://wiki.haskell.org/Template_Haskell) driven Haskell contract API generator can automatical create ABI encoding instances and contract method helpers.+        -- Get half of balance+        let halfBalance = fromWei (myBalance / 2) -    > :set -XQuasiQuotes-    > import Network.Ethereum.Contract.TH-    > putStr [abiFrom|data/sample.json|]-    Contract:-            Events:-                    Action1(address,uint256)-                    Action2(string,uint256)-            Methods:-                    0x03de48b3 runA1()-                    0x90126c7a runA2(string,uint256)+        -- Use default account+        withAccount () $ do+            -- Get Ethereum address via ENS+            alice <- Ens.resolve "alice.address.on.eth"+            bob   <- Ens.resolve "bob.address.on.eth" -Use `-ddump-splices` to see generated code during compilation or in GHCi. See `examples` folder for more use cases.+            -- Send transaction with value+            withParam (value .~ halfBalance) $ do -### Testing+                -- Send transaction to alice account+                withParam (to .~ alice) $ send () -Testing the `web3` is split up into two suites: `unit` and `live`.-The `unit` suite tests internal library facilities, while the `live` tests that-the library adequately interacts with a Web3 provider.+                -- Send transaction to bob account+                withParam (to .~ bob) $ send () -One may simply run `stack test` to run both suites, or `stack test web3:unit` or `stack test web3:live`-to run the test suites individually.+        -- Return sended value+        return halfBalance -The `unit` suite has no external dependencies, while the `live` suite requires Truffle and `jq`-to be available on your machine.+    -- Web3 error handling+    case ret of+        Left e  -> error $ show e+        Right v -> print (v :: Ether)  -- Print returned value in ethers+``` -The `live` suite also requires a Web3 provider with Ethereum capabilities, as well as-an unlocked account with ether to send transactions from. It uses Truffle to deploy testing contracts,-generating ABIs for them in the process, then using said ABIs as part of a TemplateHaskell step in the suite.-It is assumed that the provider is available at `http://localhost:8545`. If that's not the case, you must update `truffle.js`-so that Truffle can deploy the contracts correctly, and pass the `WEB3_PROVIDER=http://host:port` environment variable-when running the tests so that the `web3` library can interact with the chain that's being tested against.+---++Read more in the [documentation on ReadTheDocs](https://hs-web3.readthedocs.io).
+ cbits/solidity_lite.cpp view
@@ -0,0 +1,99 @@+#include <solidity_lite.h>+#include <libsolidity/interface/CompilerStack.h>+#include <libsolidity/interface/SourceReferenceFormatter.h>++using namespace dev::solidity;+using namespace std;++struct Solidity {+    Solidity() : compiler(new CompilerStack)+    {}++    ~Solidity()+    { delete compiler; }++    CompilerStack * compiler;+    map<string, dev::h160> libs;+};++#ifdef __cplusplus+extern "C"+{+#endif++namespace dev {+namespace solidity {+namespace lite {++void * create()+{+    return static_cast<void *>(new Solidity);+}++void destroy(void * self)+{+    delete static_cast<Solidity *>(self);+}++int addSource(void * self, const char * name, const char * source)+{+    return static_cast<Solidity*>(self)->compiler->addSource(name, source);+}++int addLibrary(void * self, const char * name, const char * address)+{+    static_cast<Solidity*>(self)->libs[name] = dev::h160(address);+    return 0;+}++int compile(void * self, int optimize)+{+    auto s = static_cast<Solidity *>(self);++    s->compiler->setOptimiserSettings(optimize);+    s->compiler->setLibraries(s->libs);+    s->compiler->reset(true);+    if (s->compiler->parseAndAnalyze()) +        if (s->compiler->compile())+            return 0;++    return -1;+}++char * c_string(const std::string &str)+{+    auto c_str = (char *) calloc(1, str.size()+1);+    memcpy(c_str, str.c_str(), str.size());+    return c_str;+}++char * abi(void * self, const char * name)+{+    auto abi_value = static_cast<Solidity *>(self)->compiler->contractABI(name);+    return c_string(abi_value.toStyledString());+}++char * binary(void * self, const char * name)+{+    auto bin_object = static_cast<Solidity *>(self)->compiler->object(name);+    return c_string(bin_object.toHex());+}++char * errors(void * self)+{+    auto compiler = static_cast<Solidity *>(self)->compiler;+    stringstream error_stream;+	for (auto const& error: compiler->errors()) {+		SourceReferenceFormatter fmt(error_stream, [&](string const& _source) -> Scanner const& { return compiler->scanner(_source); });+        fmt.printExceptionInformation(*error, (error->type() == Error::Type::Warning) ? "Warning" : "Error");+    }+    return c_string(error_stream.str());+}++} // solidity+} // lite+} // dev++#ifdef __cplusplus+}+#endif
− examples/ERC20.hs
@@ -1,11 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE DeriveGeneric         #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE QuasiQuotes           #-}-module ERC20 where--import           Network.Ethereum.Contract.TH--[abiFrom|examples/ERC20.json|]
− examples/ERC20.json
@@ -1,1 +0,0 @@-[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"delegate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"}],"name":"unapprove","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_count","type":"uint256"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]
− examples/TokenInfo.hs
@@ -1,29 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module Main where--import           Data.Default                 (def)-import           Data.Text                    (unpack)-import           Text.Printf                  (printf)--import           Network.Ethereum.Contract.TH-import           Network.Ethereum.Web3        hiding (name)--import           ERC20--main :: IO ()-main = do-    result <- runWeb3 $ do-        n <- name tokenCall-        s <- symbol tokenCall-        d <- decimals tokenCall-        return $ printf "Token %s with symbol %s and decimals %d"-                   (unpack n) (unpack s) (fromIntegral d :: Int)-    case result of-      Left err   -> print err-      Right info -> putStrLn info-  where-    token :: Address-    token = "0xA2f4FCb0FDe2dD59f7a1873e121bc5623e3164Eb"--    tokenCall :: Call-    tokenCall = def { callTo = Just token }
+ examples/token/ERC20.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE QuasiQuotes           #-}+module ERC20 where++import           Network.Ethereum.Contract.TH++[abiFrom|examples/ERC20.json|]
+ examples/token/ERC20.json view
@@ -0,0 +1,1 @@+[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"delegate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"}],"name":"unapprove","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_count","type":"uint256"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]
+ examples/token/Main.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE OverloadedStrings #-}+module Main where++import           Data.Default             (def)+import           Data.Text                (unpack)+import           Text.Printf              (printf)++import           Network.Ethereum.Account+import           Network.Ethereum.Web3    hiding (name)++import           ERC20++main :: IO ()+main = do+    result <- runWeb3 $+        withAccount () $+            airaToken $ do+                n <- name+                s <- symbol+                d <- decimals+                return $ printf "Token %s with symbol %s and decimals %d"+                   (unpack n) (unpack s) (fromIntegral d :: Int)+    case result of+      Left err   -> error err+      Right info -> putStrLn info+  where+    airaToken = withParam $ to .~ "0xA2f4FCb0FDe2dD59f7a1873e121bc5623e3164Eb"
+ src/Crypto/Ethereum.hs view
@@ -0,0 +1,59 @@+-- |+-- Module      :  Crypto.Ethereum+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Ethereum ECDSA based on secp256k1 bindings.+--++module Crypto.Ethereum+    (+    -- * Ethereum ECDSA sign/recover+      hashMessage+    , ecsign+    , ecrecover++    -- * Re-export useful Secp256k1 functions+    , SecKey+    , derivePubKey+    )where++import           Crypto.Hash                (Keccak_256 (..), hashWith)+import           Crypto.Secp256k1           (CompactRecSig, Msg, SecKey,+                                             derivePubKey, exportCompactRecSig,+                                             importCompactRecSig, msg, recover,+                                             signRecMsg)+import           Data.ByteArray             (ByteArrayAccess, convert)+import           Data.Maybe                 (fromJust)++import           Data.Solidity.Prim.Address (Address, fromPubKey)++-- | SHA3 hash of argument+hashMessage :: ByteArrayAccess ba => ba -> Msg+hashMessage = fromJust . msg . convert . hashWith Keccak_256++-- | Sign message with Ethereum private key+ecsign :: ByteArrayAccess message+       => SecKey+       -- ^ Private key+       -> message+       -- ^ Message content+       -> CompactRecSig+       -- ^ Signature+ecsign key = exportCompactRecSig . signRecMsg key . hashMessage++-- | Recover message signer Ethereum address+ecrecover :: ByteArrayAccess message+          => CompactRecSig+          -- ^ Signature+          -> message+          -- ^ Message content+          -> Maybe Address+          -- ^ Message signer address+ecrecover sig message = do+    sig' <- importCompactRecSig sig+    fromPubKey <$> recover sig' (hashMessage message)
+ src/Data/ByteArray/HexString.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-}++-- |+-- Module      :  Data.ByteArray.HexString+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Hex string data type and useful functions.+--++module Data.ByteArray.HexString where++import           Data.Aeson              (FromJSON (..), ToJSON (..),+                                          Value (String), withText)+import           Data.ByteArray          (ByteArray, ByteArrayAccess, convert)+import qualified Data.ByteArray          as BA (drop, take)+import           Data.ByteArray.Encoding (Base (Base16), convertFromBase,+                                          convertToBase)+import           Data.ByteString         (ByteString)+import           Data.Monoid             (Monoid, (<>))+import           Data.Semigroup          (Semigroup)+import           Data.String             (IsString (..))+import           Data.Text               (Text)+import           Data.Text.Encoding      (decodeUtf8, encodeUtf8)++-- | Represents a Hex string. Guarantees that all characters it contains+--   are valid hex characters.+newtype HexString = HexString { unHexString :: ByteString }+  deriving (Eq, Ord, Semigroup, Monoid, ByteArrayAccess, ByteArray)++instance Show HexString where+    show = ("HexString " ++) . show . toText++instance IsString HexString where+    fromString = hexString' . fromString+      where+        hexString' :: ByteString -> HexString+        hexString' = either error id . hexString++instance FromJSON HexString where+    parseJSON = withText "HexString" $ either fail pure . hexString . encodeUtf8++instance ToJSON HexString where+    toJSON = String . toText++-- | Smart constructor which validates that all the text are actually+--   have `0x` prefix, hexadecimal characters and length is even.+hexString :: ByteArray ba => ba -> Either String HexString+hexString bs+  | BA.take 2 bs == hexStart = HexString <$> bs'+  | otherwise  = Left "Hex string should start from '0x'"+  where+    hexStart = convert ("0x" :: ByteString)+    bs' = convertFromBase Base16 (BA.drop 2 bs)++-- | Reads a raw bytes and converts to hex representation.+fromBytes :: ByteArrayAccess ba => ba -> HexString+fromBytes = HexString . convert++-- | Access to the raw bytes of 'HexString'.+toBytes :: ByteArray ba => HexString -> ba+toBytes = convert . unHexString++-- | Access to a 'Text' representation of the 'HexString'+toText :: HexString -> Text+toText = ("0x" <>) . decodeUtf8 . convertToBase Base16 . unHexString
+ src/Data/Solidity/Abi.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE TypeFamilies      #-}++-- |+-- Module      :  Data.Solidity.Abi+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- The Application Binary Interface is the standard way to interact with contracts+-- in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract+-- interaction. Data is encoded according to its type, as described in this specification.+-- The encoding is not self describing and thus requires a schema in order to decode.+--++module Data.Solidity.Abi where++import           Data.Proxy     (Proxy)+import           Data.Serialize (Get, Putter)+import           Generics.SOP   (Generic, Rep, from, to)++-- | A class for abi encoding datatype descriptions+class AbiType a where+    isDynamic :: Proxy a -> Bool++-- | A class for encoding datatypes to their abi encoding+--+-- If your compiler has support for the @DeriveGeneric@ and+-- @DefaultSignatures@ language extensions (@ghc >= 7.2.1@),+-- the 'abiPut' method will have default generic implementations.+--+-- To use this option, simply add a @deriving 'Generic'@ clause+-- to your datatype and declare a 'AbiPut' instance for it without+-- giving a definition for 'abiPut'.+--+class AbiType a => AbiPut a where+    abiPut :: Putter a++    default abiPut :: (Generic a, Rep a ~ rep, GenericAbiPut rep) => Putter a+    abiPut = gAbiPut . from++-- | A class for encoding generically composed datatypes to their abi encoding+class GenericAbiPut a where+    gAbiPut :: Putter a++-- | A class for decoding datatypes from their abi encoding+--+-- If your compiler has support for the @DeriveGeneric@ and+-- @DefaultSignatures@ language extensions (@ghc >= 7.2.1@),+-- the 'abiGet' method will have default generic implementations.+--+-- To use this option, simply add a @deriving 'Generic'@ clause+-- to your datatype and declare a 'AbiGet' instance for it without+-- giving a definition for 'abiGet'.+--+class AbiType a => AbiGet a where+    abiGet :: Get a++    default abiGet :: (Generic a, Rep a ~ rep, GenericAbiGet rep) => Get a+    abiGet = to <$> gAbiGet++-- | A class for decoding generically composed datatypes from their abi encoding+class GenericAbiGet a where+    gAbiGet :: Get a
+ src/Data/Solidity/Abi/Codec.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE TypeFamilies #-}++-- |+-- Module      :  Data.Solidity.Abi.Codec+-- Copyright   :  Alexander Krupenkin 2017-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Solidity contract ABI encoding functions.+--++module Data.Solidity.Abi.Codec+    (+    -- * @AbiPut@/@AbiGet@ type class encoding+      encode+    , decode++    -- * Generic encoding+    , encode'+    , decode'+    ) where++import           Data.ByteArray            (ByteArray, ByteArrayAccess, convert)+import           Data.Serialize            (runGet, runPut)+import           Generics.SOP              (Generic, Rep, from, to)++import           Data.Solidity.Abi         (AbiGet (..), AbiPut (..),+                                            GenericAbiGet (..),+                                            GenericAbiPut (..))+import           Data.Solidity.Abi.Generic ()++-- | Encode datatype to Ethereum Abi-encoding+encode :: (AbiPut a, ByteArray ba)+       => a+       -> ba+{-# INLINE encode #-}+encode = convert . runPut . abiPut++-- | Generic driven version of 'encode'+encode' :: (Generic a,+            Rep a ~ rep,+            GenericAbiPut rep,+            ByteArray ba)+        => a+        -> ba+{-# INLINE encode' #-}+encode' = convert . runPut . gAbiPut . from++-- | Decode datatype from Ethereum Abi-encoding+decode :: (ByteArrayAccess ba, AbiGet a)+       => ba+       -> Either String a+{-# INLINE decode #-}+decode = runGet abiGet . convert++-- | Generic driven version of 'decode'+decode' :: (Generic a,+            Rep a ~ rep,+            GenericAbiGet rep,+            ByteArrayAccess ba)+        => ba+        -> Either String a+decode' = runGet (to <$> gAbiGet) . convert
+ src/Data/Solidity/Abi/Generic.hs view
@@ -0,0 +1,123 @@+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeInType          #-}+{-# LANGUAGE TypeOperators       #-}++-- |+-- Module      :  Data.Solidity.Abi.Generic+-- Copyright   :  Alexander Krupenkin 2017-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- This module is internal, the purpose is to define helper classes and functions+-- to assist in encoding and decoding Solidity types for function calls and events.+-- The user of this library should have no need to use this directly in application code.+--++module Data.Solidity.Abi.Generic () where++import qualified Data.ByteString.Lazy   as LBS+import           Data.Int               (Int64)+import qualified Data.List              as L+import           Data.Monoid            ((<>))+import           Data.Proxy             (Proxy (..))+import           Data.Serialize         (Get, Put)+import           Data.Serialize.Get     (bytesRead, lookAheadE, skip)+import           Data.Serialize.Put     (runPutLazy)+import           Generics.SOP           (I (..), NP (..), NS (..), SOP (..))++import           Data.Solidity.Abi      (AbiGet (..), AbiPut (..), AbiType (..),+                                         GenericAbiGet (..), GenericAbiPut (..))+import           Data.Solidity.Prim.Int (getWord256, putWord256)++data EncodedValue =+  EncodedValue { order    :: Int64+               , offset   :: Maybe Int64+               , encoding :: Put+               }++instance Eq EncodedValue where+  ev1 == ev2 = order ev1 == order ev2++instance Ord EncodedValue where+  compare ev1 ev2 = order ev1 `compare` order ev2++combineEncodedValues :: [EncodedValue] -> Put+combineEncodedValues encodings =+  let sortedEs = adjust headsOffset $ L.sort encodings+      encodings' = addTailOffsets headsOffset [] sortedEs+  in let heads = foldl (\acc EncodedValue{..} -> case offset of+                          Nothing -> acc <> encoding+                          Just o  -> acc <> putWord256 (fromIntegral o)+                      ) mempty encodings'+         tails = foldl (\acc EncodedValue{..} -> case offset of+                          Nothing -> acc+                          Just _  -> acc <> encoding+                      ) mempty encodings'+      in heads <> tails+  where+    adjust :: Int64 -> [EncodedValue] -> [EncodedValue]+    adjust n = map (\ev -> ev {offset = (+) n <$> offset ev})+    addTailOffsets :: Int64 -> [EncodedValue] -> [EncodedValue] -> [EncodedValue]+    addTailOffsets init' acc es = case es of+      [] -> reverse acc+      (e : tail') -> case offset e of+        Nothing -> addTailOffsets init' (e : acc) tail'+        Just _  -> addTailOffsets init' (e : acc) (adjust (LBS.length . runPutLazy . encoding $ e) tail')+    headsOffset :: Int64+    headsOffset = foldl (\acc e -> case offset e of+                                Nothing -> acc + (LBS.length . runPutLazy . encoding $ e)+                                Just _ -> acc + 32+                            ) 0 encodings++class AbiData a where+    _serialize :: [EncodedValue] -> a -> [EncodedValue]++instance AbiData (NP f '[]) where+    _serialize encoded _ = encoded++instance (AbiType b, AbiPut b, AbiData (NP I as)) => AbiData (NP I (b :as)) where+    _serialize encoded (I b :* a) =+        if isDynamic (Proxy :: Proxy b)+        then _serialize (dynEncoding  : encoded) a+        else _serialize (staticEncoding : encoded) a+      where+        staticEncoding = EncodedValue { encoding = abiPut b+                                      , offset = Nothing+                                      , order = 1 + (fromInteger . toInteger . L.length $ encoded)+                                      }+        dynEncoding = EncodedValue { encoding = abiPut b+                                   , offset = Just 0+                                   , order = 1 + (fromInteger . toInteger . L.length $ encoded)+                                   }++instance AbiData (NP f as) => GenericAbiPut (SOP f '[as]) where+    gAbiPut (SOP (Z a)) = combineEncodedValues $ _serialize [] a+    gAbiPut _           = error "Impossible branch"++instance GenericAbiGet (NP f '[]) where+    gAbiGet = return Nil++instance (AbiGet a, GenericAbiGet (NP I as)) => GenericAbiGet (NP I (a : as)) where+    gAbiGet = (:*) <$> (I <$> factorParser) <*> gAbiGet++instance GenericAbiGet (NP f as) => GenericAbiGet (SOP f '[as]) where+    gAbiGet = SOP . Z <$> gAbiGet++factorParser :: forall a . AbiGet a => Get a+factorParser+  | not $ isDynamic (Proxy :: Proxy a) = abiGet+  | otherwise = do+        dataOffset <- fromIntegral <$> getWord256+        currentOffset <- bytesRead+        Left x <- lookAheadE $ do+            skip (dataOffset - currentOffset)+            Left <$> abiGet+        return x
+ src/Data/Solidity/Event.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE DataKinds              #-}+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE PolyKinds              #-}+{-# LANGUAGE ScopedTypeVariables    #-}+{-# LANGUAGE TypeFamilies           #-}+{-# LANGUAGE TypeOperators          #-}+{-# LANGUAGE UndecidableInstances   #-}++-- |+-- Module      :  Data.Solidity.Event+-- Copyright   :  Alexander Krupenkin 2017-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- This module is internal, the purpose is to define+-- helper classes and functions to assist in event decoding.+-- The user of this library should have no need to use+-- this directly in application code.+--++module Data.Solidity.Event+    (+      DecodeEvent(..)+    , IndexedEvent(..)+    ) where++import           Data.ByteArray               (ByteArrayAccess)+import           Data.Proxy                   (Proxy (..))+import           Generics.SOP                 (Generic, I (..), NP (..),+                                               NS (..), Rep, SOP (..), from, to)++import           Data.Solidity.Abi            (AbiGet)+import           Data.Solidity.Abi.Codec      (decode)+import           Data.Solidity.Event.Internal+import           Network.Ethereum.Api.Types   (Change (..))++-- | Indexed event args come back in as a list of encoded values. 'ArrayParser'+-- | is used to decode these values so that they can be used to reconstruct the+-- | entire decoded event.+class ArrayParser a where+  arrayParser :: ByteArrayAccess ba+              => [ba]+              -> Either String a++instance ArrayParser (NP f '[]) where+  arrayParser _ = Right Nil++instance (ArrayParser (NP I as), AbiGet a)+       => ArrayParser (NP I (a : as)) where+  arrayParser [] = Left "Empty"+  arrayParser (a : as) = do+    a' <- decode a+    as' <- arrayParser as+    return $ I a' :* as'++instance ArrayParser (NP f as) => ArrayParser (SOP f '[as]) where+  arrayParser = fmap (SOP . Z) . arrayParser++genericArrayParser :: ( Generic a+                      , Rep a ~ rep+                      , ArrayParser rep+                      , ByteArrayAccess ba+                      )+                   => [ba]+                   -> Either String a+genericArrayParser = fmap to . arrayParser++--------------------------------------------------------------------------------+-- Event Parsing+--------------------------------------------------------------------------------++data Event i ni = Event i ni++-- | 'parseChange' decodes both the indexed and non-indexed event components.+parseChange :: ( Generic i+               , Rep i ~ irep+               , ArrayParser irep+               , AbiGet ni+               )+             => Change+             -> Bool+             -- ^ is anonymous event+             -> Either String (Event i ni)+parseChange change anonymous =+    Event <$> genericArrayParser topics <*> decode data_+  where+    topics | anonymous = changeTopics change+           | otherwise = tail (changeTopics change)+    data_ = changeData change++class IndexedEvent i ni e | e -> i ni where+  isAnonymous :: Proxy e -> Bool++-- | 'CombineChange' is a class which indicates that given event components of types 'i'+-- | and 'ni', we can construct an event of type 'e'. The functional dependency is valid+-- | becasue of how the template haskell generates the event types.+class CombineChange i ni e | e -> i ni where+  combineChange :: i -> ni -> e++instance ( Generic i+         , Rep i ~ irep+         , Generic ni+         , Rep ni ~ nirep+         , Generic e+         , Rep e ~ erep+         , HListRep irep hli+         , HListRep nirep hlni+         , MergeIndexedArguments hli hlni+         , MergeIndexedArguments' hli hlni ~ hle+         , HListRep erep hle+         , IndexedEvent i ni e+         ) => CombineChange i ni e where+  combineChange i ni =+    let hli = toHList . from $ i+        hlni = toHList . from $ ni+        hle = mergeIndexedArguments hli hlni+    in to . fromHList $ hle++class DecodeEvent i ni e | e -> i ni where+  decodeEvent :: Change -> Either String e++instance ( IndexedEvent i ni e+         , Generic i+         , Rep i ~ SOP I '[hli]+         , AbiGet ni+         , Generic ni+         , Rep ni ~ SOP I '[hlni]+         , Generic e+         , Rep e ~ SOP I '[hle]+         , CombineChange i ni e+         , ArrayParser (SOP I '[hli])+         ) => DecodeEvent i ni e where+  decodeEvent change = do+      let anonymous = isAnonymous (Proxy :: Proxy e)+      (Event i ni :: Event i ni) <- parseChange change anonymous+      return $ combineChange i ni
+ src/Data/Solidity/Event/Internal.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE DataKinds              #-}+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GADTs                  #-}+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE PolyKinds              #-}+{-# LANGUAGE ScopedTypeVariables    #-}+{-# LANGUAGE TypeFamilies           #-}+{-# LANGUAGE TypeInType             #-}+{-# LANGUAGE TypeOperators          #-}+{-# LANGUAGE UndecidableInstances   #-}++-- |+-- Module      :  Data.Solidity.Event.Internal+-- Copyright   :  Alexander Krupenkin 2017-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- This module is internal, the purpose is to define helper classes and types+-- to assist in event decoding. The user of this library should have no need to use+-- this directly in application code.+--++module Data.Solidity.Event.Internal where++import           Data.Kind    (Type)+import           Data.Proxy   (Proxy (..))+import           Data.Tagged  (Tagged (..))+import           Generics.SOP (I (..), NP (..), NS (..), SOP (..))+import           GHC.TypeLits (CmpNat)++data HList :: [Type] -> Type where+  HNil :: HList '[]+  (:<) :: a -> HList as -> HList (a : as)++infixr 0 :<++-- | Generic representation to HList representation+class HListRep a xs | a -> xs, a -> xs where+  toHList :: a -> HList xs+  fromHList :: HList xs -> a++instance HListRep (NP I '[]) '[] where+  toHList _ = HNil+  fromHList _ = Nil++instance HListRep (NP I as) as => HListRep (NP I (a:as)) (a:as) where+  toHList (I a :* rest) = a :< toHList rest+  fromHList (a :< rest) = I a :* fromHList rest++instance HListRep (NP f as') as => HListRep (SOP f '[as']) as where+  toHList (SOP (Z rep)) = toHList rep+  toHList _             = error "Impossible branch"+  fromHList = SOP . Z . fromHList++-- | Sort a Tagged HList+class Sort (xs :: [Type]) where+  type Sort' xs :: [Type]+  sort :: HList xs -> HList (Sort' xs)++instance Sort '[] where+  type Sort' '[] = '[]+  sort HNil = HNil++instance (Sort xs, Insert x (Sort' xs)) => Sort (x : xs) where+  type Sort' (x : xs) = Insert' x (Sort' xs)+  sort (x :< xs) = insert x (sort xs)++class Insert (x :: Type) (xs :: [Type]) where+  type Insert' x xs :: [Type]+  insert :: x -> HList xs -> HList (Insert' x xs)++instance Insert x '[] where+  type Insert' x '[] = '[x]+  insert x HNil = x :< HNil++instance InsertCmp (CmpNat n m) (Tagged n x) (Tagged m y) ys => Insert (Tagged n x) (Tagged m y : ys) where+  type Insert' (Tagged n x) (Tagged m y : ys) = InsertCmp' (CmpNat n m) (Tagged n x) (Tagged m y) ys+  insert (x :: Tagged n x) ((y :: Tagged m y) :< ys) = insertCmp (Proxy :: Proxy (CmpNat n m)) x y ys++class InsertCmp (b :: Ordering) (x :: Type) (y :: Type) (ys :: [Type]) where+  type InsertCmp' b x y ys :: [Type]+  insertCmp :: Proxy (b :: Ordering) -> x -> y -> HList ys -> HList (InsertCmp' b x y ys)++instance InsertCmp 'LT x y ys where+  type InsertCmp' 'LT x y ys = x : (y : ys)+  insertCmp _ x y ys = x :< y :< ys++instance Insert x ys => InsertCmp 'GT x y ys where+  type InsertCmp' 'GT x y ys = y : Insert' x ys+  insertCmp _ x y ys = y :< insert x ys++-- | Unwrap all the Tagged items in an HList+class UnTag t where+  type UnTag' t :: [Type]+  unTag :: HList t -> HList (UnTag' t)++instance UnTag '[] where+  type UnTag' '[] = '[]+  unTag a = a++instance UnTag ts => UnTag (Tagged n a : ts) where+  type UnTag' (Tagged n a : ts) = a : UnTag' ts+  unTag (Tagged a :< ts) = a :< unTag ts++class HListMerge (as :: [Type]) (bs :: [Type]) where+  type Concat as bs :: [Type]+  mergeHList :: HList as -> HList bs -> HList (Concat as bs)++instance HListMerge '[] bs where+  type Concat '[] bs = bs+  mergeHList _ bs = bs++instance HListMerge as bs => HListMerge (a : as) bs where+  type Concat (a : as) bs = a : Concat as bs+  mergeHList (a :< as) bs = a :< mergeHList as bs++class HListMergeSort as bs where+  type MergeSort' as bs :: [Type]+  mergeSortHList :: HList as -> HList bs -> HList (MergeSort' as bs)++instance (HListMerge as bs, Concat as bs ~ cs, Sort cs, Sort' cs ~ cs') => HListMergeSort as bs where+  type MergeSort' as bs = Sort' (Concat as bs)+  mergeSortHList as bs = sort $ (mergeHList as bs :: HList cs)++class MergeIndexedArguments as bs where+  type MergeIndexedArguments' as bs :: [Type]+  mergeIndexedArguments :: HList as -> HList bs -> HList (MergeIndexedArguments' as bs)++instance (HListMergeSort as bs, MergeSort' as bs ~ cs, UnTag cs, UnTag cs' ~ ds) => MergeIndexedArguments as bs where+  type MergeIndexedArguments' as bs = (UnTag' (MergeSort' as bs))+  mergeIndexedArguments as bs = unTag $ mergeSortHList as bs
+ src/Data/Solidity/Prim.hs view
@@ -0,0 +1,30 @@+-- |+-- Module      :  Data.Solidity.Prim+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Solidity primitive data types.+--++module Data.Solidity.Prim+    (+      Address+    , Bytes+    , BytesN+    , IntN+    , UIntN+    , ListN+    ) where++import           Data.Solidity.Prim.Address (Address)+import           Data.Solidity.Prim.Bool    ()+import           Data.Solidity.Prim.Bytes   (Bytes, BytesN)+import           Data.Solidity.Prim.Int     (IntN, UIntN)+import           Data.Solidity.Prim.List    (ListN)+import           Data.Solidity.Prim.String  ()+import           Data.Solidity.Prim.Tagged  ()+import           Data.Solidity.Prim.Tuple   ()
+ src/Data/Solidity/Prim/Address.hs view
@@ -0,0 +1,123 @@+{-# LANGUAGE DataKinds         #-}+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module      :  Data.Solidity.Prim.Address+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Ethreum account address.+--++module Data.Solidity.Prim.Address+    (+    -- * The @Address@ type+      Address++    -- * Hex string encoding+    , toHexString+    , fromHexString++    -- * Public key to @Address@ convertor+    , fromPubKey++    -- * EIP55 Mix-case checksum address encoding+    , toChecksum+    , verifyChecksum+    ) where++import           Control.Monad            ((<=<))+import           Crypto.Hash              (Keccak_256 (..), hashWith)+import           Crypto.Secp256k1         (PubKey, exportPubKey)+import           Data.Aeson               (FromJSON (..), ToJSON (..))+import           Data.Bits                ((.&.))+import           Data.Bool                (bool)+import           Data.ByteArray           (convert, zero)+import qualified Data.ByteArray           as BA (drop)+import           Data.ByteString          (ByteString)+import qualified Data.ByteString          as BS (take, unpack)+import qualified Data.ByteString.Char8    as C8 (drop, length, pack, unpack)+import qualified Data.Char                as C (toLower, toUpper)+import           Data.Default             (Default (..))+import           Data.Monoid              ((<>))+import           Data.String              (IsString (..))+import           Data.Text.Encoding       as T (encodeUtf8)+import           Generics.SOP             (Generic)+import qualified GHC.Generics             as GHC (Generic)++import           Data.ByteArray.HexString (HexString, fromBytes, toBytes,+                                           toText)+import           Data.Solidity.Abi        (AbiGet (..), AbiPut (..),+                                           AbiType (..))+import           Data.Solidity.Abi.Codec  (decode, encode)+import           Data.Solidity.Prim.Int   (UIntN)++-- | Ethereum account address+newtype Address = Address { unAddress :: UIntN 160 }+  deriving (Eq, Ord, GHC.Generic)++instance Generic Address++instance Default Address where+    def = Address 0++instance Show Address where+    show = show . toChecksum . T.encodeUtf8 . toText . toHexString++instance IsString Address where+    fromString = either error id . fromHexString . fromString++instance AbiType Address where+    isDynamic _ = False++instance AbiGet Address where+    abiGet = Address <$> abiGet++instance AbiPut Address where+    abiPut = abiPut . unAddress++instance FromJSON Address where+    parseJSON = (either fail pure . fromHexString) <=< parseJSON++instance ToJSON Address where+    toJSON = toJSON . toHexString++-- | Derive address from secp256k1 public key+fromPubKey :: PubKey -> Address+fromPubKey key =+    case decode $ zero 12 <> BA.drop 12 (sha3 key) of+        Right a -> a+        Left e  -> error $ "Impossible error: " ++ e+  where+    sha3 :: PubKey -> ByteString+    sha3 = convert . hashWith Keccak_256 . BA.drop 1 . exportPubKey False++-- | Decode address from hex string+fromHexString :: HexString -> Either String Address+fromHexString bs+  | bslen == 20 = decode (zero 12 <> toBytes bs :: ByteString)+  | otherwise = Left $ "Incorrect address length: " ++ show bslen+  where bslen = C8.length (toBytes bs)++-- | Encode address to hex string+toHexString :: Address -> HexString+toHexString = fromBytes . C8.drop 12 . encode++-- | Encode address with mixed-case checksum+-- https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md+toChecksum :: ByteString -> ByteString+toChecksum addr = ("0x" <>) . C8.pack $ zipWith ($) upcaseVector lower+  where+    upcaseVector = (>>= fourthBits) . BS.unpack . BS.take 20 . convert $ hashWith Keccak_256 (C8.pack lower)+    fourthBits n = bool id C.toUpper <$> [n .&. 0x80 /= 0, n .&. 0x08 /= 0]+    lower = drop 2 . fmap C.toLower . C8.unpack $ addr++-- | Verify mixed-case address checksum+-- https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md+verifyChecksum :: ByteString -> Bool+verifyChecksum = toChecksum >>= (==)
+ src/Data/Solidity/Prim/Bool.hs view
@@ -0,0 +1,25 @@+-- |+-- Module      :  Data.Solidity.Prim.Bool+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Ethereum Abi boolean type.+--++module Data.Solidity.Prim.Bool () where++import           Data.Solidity.Abi      (AbiGet (..), AbiPut (..), AbiType (..))+import           Data.Solidity.Prim.Int (getWord256, putWord256)++instance AbiType Bool where+    isDynamic _ = False++instance AbiGet Bool where+    abiGet = toEnum . fromIntegral <$> getWord256++instance AbiPut Bool where+    abiPut = putWord256 . fromIntegral . fromEnum
+ src/Data/Solidity/Prim/Bytes.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-}++-- |+-- Module      :  Data.Solidity.Prim.Bytes+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Bytes and BytesN primitive types.+--++module Data.Solidity.Prim.Bytes+    (+    -- * The dynamic length @Bytes@ type+      Bytes++    -- * The fixed length @BytesN@ type+    , BytesN+    ) where++import           Control.Monad           (unless)+import           Data.Aeson              (FromJSON (..), ToJSON (..),+                                          Value (String))+import           Data.ByteArray          (Bytes, convert, length, zero)+import           Data.ByteArray.Encoding (Base (Base16), convertFromBase,+                                          convertToBase)+import           Data.ByteArray.Sized    (SizedByteArray, unSizedByteArray,+                                          unsafeFromByteArrayAccess)+import qualified Data.ByteArray.Sized    as S (take)+import           Data.ByteString         (ByteString)+import qualified Data.ByteString.Char8   as C8+import           Data.Monoid             ((<>))+import           Data.Proxy              (Proxy (..))+import           Data.Serialize          (Get, Putter, getBytes, putByteString)+import           Data.String             (IsString (..))+import qualified Data.Text               as T (append, drop, take)+import           Data.Text.Encoding      (decodeUtf8, encodeUtf8)+import           GHC.TypeLits+import           Prelude                 hiding (length)++import           Data.Solidity.Abi       (AbiGet (..), AbiPut (..),+                                          AbiType (..))+import           Data.Solidity.Prim.Int  (getWord256, putWord256)++instance AbiType ByteString where+    isDynamic _ = True++instance AbiGet ByteString where+    abiGet = abiGetByteString++instance AbiPut ByteString where+    abiPut = abiPutByteString++instance AbiType Bytes where+    isDynamic _ = True++instance AbiGet Bytes where+    abiGet = convert <$> abiGetByteString++instance AbiPut Bytes where+    abiPut = abiPutByteString . convert++instance IsString Bytes where+    fromString ('0' : 'x' : hex) = either error id $ convertFromBase Base16 (C8.pack hex)+    fromString str               = convert (C8.pack str)++instance FromJSON Bytes where+    parseJSON (String hex)+        | T.take 2 hex == "0x" =+            either fail pure $ convertFromBase Base16 $ encodeUtf8 $ T.drop 2 hex+        | otherwise = fail "Hex string should have '0x' prefix"+    parseJSON _ = fail "Bytes should be encoded as hex string"++instance ToJSON Bytes where+    toJSON = toJSON . T.append "0x" . decodeUtf8 . convertToBase Base16++-- | Sized byte array with fixed length in bytes+type BytesN n = SizedByteArray n Bytes++instance (n <= 32) => AbiType (BytesN n) where+    isDynamic _ = False++instance (KnownNat n, n <= 32) => AbiGet (BytesN n) where+    abiGet = do+        ba <- unsafeFromByteArrayAccess <$> getBytes 32+        return $ S.take (ba :: BytesN 32)++instance (KnownNat n, n <= 32) => AbiPut (BytesN n) where+    abiPut ba = putByteString $ convert ba <> zero (32 - len)+      where len = fromIntegral $ natVal (Proxy :: Proxy n)++instance (KnownNat n, n <= 32) => IsString (BytesN n) where+    fromString s = unsafeFromByteArrayAccess padded+      where bytes = fromString s :: Bytes+            len = fromIntegral $ natVal (Proxy :: Proxy n)+            padded = bytes <> zero (len - length bytes)++instance (KnownNat n, n <= 32) => FromJSON (BytesN n) where+    parseJSON v = do ba <- parseJSON v+                     return $ unsafeFromByteArrayAccess (ba :: Bytes)++instance (KnownNat n, n <= 32) => ToJSON (BytesN n) where+    toJSON ba = toJSON (unSizedByteArray ba :: Bytes)++abiGetByteString :: Get ByteString+abiGetByteString = do+    len <- fromIntegral <$> getWord256+    if len == 0+        then return ""+        else getBytes len++abiPutByteString :: Putter ByteString+abiPutByteString bs = do+    putWord256 $ fromIntegral len+    unless (len == 0) $+      putByteString $ bs <> zero (32 - len `mod` 32)+  where len = length bs
+ src/Data/Solidity/Prim/Int.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE DataKinds                  #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures             #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeOperators              #-}++-- |+-- Module      :  Data.Solidity.Prim.Int+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Ethereum Abi intN and uintN types.+--++module Data.Solidity.Prim.Int+    (+    -- * The @IntN@ type+      IntN++    -- * The @UIntN@ type+    , UIntN++    -- * @Word256@ serializers+    , getWord256+    , putWord256+    ) where++import qualified Basement.Numerical.Number as Basement (toInteger)+import           Basement.Types.Word256    (Word256 (Word256))+import qualified Basement.Types.Word256    as Basement (quot, rem)+import           Data.Bits                 (Bits (testBit), (.&.))+import           Data.Proxy                (Proxy (..))+import           Data.Serialize            (Get, Putter, Serialize (get, put))+import           GHC.Generics              (Generic)+import           GHC.TypeLits++import           Data.Solidity.Abi         (AbiGet (..), AbiPut (..),+                                            AbiType (..))++instance Real Word256 where+    toRational = toRational . toInteger++instance Integral Word256 where+    toInteger = Basement.toInteger+    quotRem a b = (Basement.quot a b, Basement.rem a b)++-- | Unsigned integer with fixed length in bits+newtype UIntN (n :: Nat) = UIntN { unUIntN :: Word256 }+    deriving (Eq, Ord, Enum, Bits, Generic)++instance (KnownNat n, n <= 256) => Num (UIntN n) where+    a + b  = fromInteger (toInteger a + toInteger b)+    a - b  = fromInteger (toInteger a - toInteger b)+    a * b  = fromInteger (toInteger a * toInteger b)+    abs    = fromInteger . abs . toInteger+    negate = fromInteger . negate . toInteger+    signum = fromInteger . signum . toInteger+    fromInteger x+      | x >= 0 = mask $ UIntN (fromInteger x)+      | otherwise = mask $ UIntN (fromInteger $ 2 ^ 256 + x)+      where+        mask = (maxBound .&.) :: UIntN n -> UIntN n++instance (KnownNat n, n <= 256) => Show (UIntN n) where+    show = show . unUIntN++instance (KnownNat n, n <= 256) => Bounded (UIntN n) where+    minBound = UIntN 0+    maxBound = UIntN $ 2 ^ natVal (Proxy :: Proxy n) - 1++instance (KnownNat n, n <= 256) => Real (UIntN n) where+    toRational = toRational . toInteger++instance (KnownNat n, n <= 256) => Integral (UIntN n) where+    toInteger = toInteger . unUIntN+    quotRem (UIntN a) (UIntN b) = (UIntN $ quot a b, UIntN $ rem a b)++instance (n <= 256) => AbiType (UIntN n) where+    isDynamic _ = False++instance (n <= 256) => AbiGet (UIntN n) where+    abiGet = UIntN <$> getWord256++instance (n <= 256) => AbiPut (UIntN n) where+    abiPut = putWord256 . unUIntN++-- Signed integer with fixed length in bits+newtype IntN (n :: Nat) = IntN { unIntN :: Word256 }+    deriving (Eq, Ord, Enum, Bits, Generic)++instance (KnownNat n, n <= 256) => Show (IntN n) where+    show = show . toInteger++instance (KnownNat n, n <= 256) => Bounded (IntN n) where+    minBound = IntN $ negate $ 2 ^ (natVal (Proxy :: Proxy (n :: Nat)) - 1)+    maxBound = IntN $ 2 ^ (natVal (Proxy :: Proxy (n :: Nat)) - 1) - 1++instance (KnownNat n, n <= 256) => Num (IntN n) where+    a + b  = fromInteger (toInteger a + toInteger b)+    a - b  = fromInteger (toInteger a - toInteger b)+    a * b  = fromInteger (toInteger a * toInteger b)+    abs    = fromInteger . abs . toInteger+    negate = fromInteger . negate . toInteger+    signum = fromInteger . signum . toInteger+    fromInteger x+      | x >= 0 = IntN (fromInteger x)+      | otherwise = IntN (fromInteger $ 2 ^ 256 + x)++instance (KnownNat n, n <= 256) => Real (IntN n) where+    toRational = toRational . toInteger++instance (KnownNat n, n <= 256) => Integral (IntN n) where+    quotRem (IntN a) (IntN b) = (IntN $ quot a b, IntN $ rem a b)+    toInteger x+      | testBit x 255 = toInteger (unIntN x) - 2 ^ 256+      | otherwise = toInteger $ unIntN x++instance (n <= 256) => AbiType (IntN n) where+    isDynamic _ = False++instance (n <= 256) => AbiGet (IntN n) where+    abiGet = IntN <$> getWord256++instance (n <= 256) => AbiPut (IntN n) where+    abiPut = putWord256 . unIntN++putWord256 :: Putter Word256+putWord256 (Word256 a3 a2 a1 a0) =+    put a3 >> put a2 >> put a1 >> put a0++getWord256 :: Get Word256+getWord256 = Word256 <$> get <*> get <*> get <*> get
+ src/Data/Solidity/Prim/List.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE UndecidableInstances #-}++-- |+-- Module      :  Data.Solidity.Prim.List+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Ethereum Abi dynamic and static size vectors based on linked lists.+--++module Data.Solidity.Prim.List+    (+    -- * Fixed size linked list+      ListN+    ) where++import           Basement.Nat           (NatWithinBound)+import           Basement.Sized.List    (ListN, toListN_, unListN)+import qualified Basement.Sized.List    as SL (mapM_, replicateM)+import           Control.Monad          (replicateM)+import           GHC.Exts               (IsList (..))+import           GHC.TypeLits           (KnownNat)++import           Data.Solidity.Abi      (AbiGet (..), AbiPut (..), AbiType (..))+import           Data.Solidity.Prim.Int (getWord256, putWord256)++instance AbiType [a] where+    isDynamic _ = True++instance AbiPut a => AbiPut [a] where+    abiPut l = do putWord256 $ fromIntegral (length l)+                  foldMap abiPut l++instance AbiGet a => AbiGet [a] where+    abiGet = do len <- fromIntegral <$> getWord256+                replicateM len abiGet++instance AbiType (ListN n a) where+    isDynamic _ = False++instance AbiPut a => AbiPut (ListN n a) where+    abiPut = SL.mapM_ abiPut++instance (NatWithinBound Int n, KnownNat n, AbiGet a) => AbiGet (ListN n a) where+    abiGet = SL.replicateM abiGet++instance (NatWithinBound Int n, KnownNat n) => IsList (ListN n a) where+    type Item (ListN n a) = a+    fromList = toListN_+    toList   = unListN
+ src/Data/Solidity/Prim/String.hs view
@@ -0,0 +1,29 @@+-- |+-- Module      :  Data.Solidity.Prim.String+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Ethereum Abi UTF8-encoded string type.+--++module Data.Solidity.Prim.String where++import           Data.Text                (Text)+import           Data.Text.Encoding       (decodeUtf8, encodeUtf8)++import           Data.Solidity.Abi        (AbiGet (..), AbiPut (..),+                                           AbiType (..))+import           Data.Solidity.Prim.Bytes ()++instance AbiType Text where+    isDynamic _ = True++instance AbiPut Text where+    abiPut = abiPut . encodeUtf8++instance AbiGet Text where+    abiGet = decodeUtf8 <$> abiGet
+ src/Data/Solidity/Prim/Tagged.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE PolyKinds           #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+-- Module      :  Data.Solidity.Prim.Tagged+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Ethereum Abi tagged types.+--++module Data.Solidity.Prim.Tagged+    (+    -- * The @Tagged@ type+      Tagged+    ) where++import           Data.Proxy        (Proxy (..))+import           Data.Tagged       (Tagged (..))+import           Generics.SOP      (Generic)++import           Data.Solidity.Abi (AbiGet (..), AbiPut (..), AbiType (..))++instance AbiType a => AbiType (Tagged t a) where+    isDynamic _ = isDynamic (Proxy :: Proxy a)++instance AbiPut a => AbiPut (Tagged t a) where+    abiPut (Tagged a) = abiPut a++instance AbiGet a => AbiGet (Tagged t a) where+    abiGet = Tagged <$> abiGet++instance Generic a => Generic (Tagged t a)
+ src/Data/Solidity/Prim/Tuple.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving  #-}+{-# LANGUAGE TemplateHaskell     #-}++-- |+-- Module      :  Data.Solidity.Prim.Tuple+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- Tuple type abi encoding instances.+--++module Data.Solidity.Prim.Tuple where++import           Data.Proxy                  (Proxy (..))+import           Data.Tuple.OneTuple         (OneTuple (..))+import           Generics.SOP                (Generic)+import qualified GHC.Generics                as GHC (Generic)++import           Data.Solidity.Abi           (AbiGet, AbiPut, AbiType (..))+import           Data.Solidity.Abi.Generic   ()+import           Data.Solidity.Prim.Tuple.TH (tupleDecs)++deriving instance GHC.Generic (OneTuple a)+instance Generic (OneTuple a)++instance AbiType a => AbiType (OneTuple a) where+    isDynamic _ = isDynamic (Proxy :: Proxy a)++instance AbiGet a => AbiGet (OneTuple a)+instance AbiPut a => AbiPut (OneTuple a)++$(concat <$> mapM tupleDecs [2..20])
+ src/Data/Solidity/Prim/Tuple/TH.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE TemplateHaskell #-}++-- |+-- Module      :  Data.Solidity.Prim.Tuple.TH+-- Copyright   :  Alexander Krupenkin 2016-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- This module is for internal usage only.+-- It contains tuple abi encoding template haskell generator.+--++module Data.Solidity.Prim.Tuple.TH (tupleDecs) where+++import           Control.Monad       (replicateM)+import           Language.Haskell.TH (DecsQ, Type (VarT), appT, clause, conT,+                                      cxt, funD, instanceD, newName, normalB,+                                      tupleT)++import           Data.Solidity.Abi   (AbiGet, AbiPut, AbiType (..))++tupleDecs :: Int -> DecsQ+tupleDecs n = do+    vars <- replicateM n $ newName "a"+    let types = fmap (pure . VarT) vars+    sequence $+      [ instanceD (cxt $ map (appT $ conT ''AbiType) types) (appT (conT ''AbiType) (foldl appT (tupleT n) types))+          [funD 'isDynamic [clause [] (normalB [|const False|]) []]]+      , instanceD (cxt $ map (appT $ conT ''AbiGet) types) (appT (conT ''AbiGet) (foldl appT (tupleT n) types)) []+      , instanceD (cxt $ map (appT $ conT ''AbiPut) types) (appT (conT ''AbiPut) (foldl appT (tupleT n) types)) [] ]
src/Data/String/Extra.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Data.String.Extra--- Copyright   :  Alexander Krupenkin 2016-2018+-- Copyright   :  Alexander Krupenkin 2016 -- License     :  BSD3 -- -- Maintainer  :  mail@akru.me
+ src/Language/Solidity/Abi.hs view
@@ -0,0 +1,284 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell   #-}++-- |+-- Module      :  Data.Solidity.Abi.Json+-- Copyright   :  Alexander Krupenkin 2016-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  noportable+--+-- JSON encoded contract ABI parsers.+--++module Language.Solidity.Abi+    (+    -- * Contract ABI declarations+      ContractAbi(..)+    , Declaration(..)+    , FunctionArg(..)+    , EventArg(..)++    -- * Method/Event id encoder+    , signature+    , methodId+    , eventId++    -- * Solidity type parser+    , SolidityType(..)+    , parseSolidityType+    ) where++import           Control.Monad      (void)+import           Crypto.Hash        (Digest, Keccak_256, hash)+import           Data.Aeson         (FromJSON (parseJSON), Options (constructorTagModifier, fieldLabelModifier, sumEncoding),+                                     SumEncoding (TaggedObject),+                                     ToJSON (toJSON), defaultOptions)+import           Data.Aeson.TH      (deriveJSON)+import           Data.Monoid        ((<>))+import           Data.Text          (Text)+import qualified Data.Text          as T (dropEnd, pack, take, unlines, unpack)+import           Data.Text.Encoding (encodeUtf8)+import           Text.Parsec        (ParseError, char, choice, digit, eof,+                                     lookAhead, many1, manyTill, optionMaybe,+                                     parse, string, try, (<|>))+import           Text.Parsec.Text   (Parser)++import           Data.String.Extra  (toLowerFirst)++-- | Method argument+data FunctionArg = FunctionArg+  { funArgName :: Text+  -- ^ Argument name+  , funArgType :: Text+  -- ^ Argument type+  } deriving (Show, Eq, Ord)++$(deriveJSON+    (defaultOptions {fieldLabelModifier = toLowerFirst . drop 6})+    ''FunctionArg)++-- | Event argument+data EventArg = EventArg+  { eveArgName    :: Text+  -- ^ Argument name+  , eveArgType    :: Text+  -- ^ Argument type+  , eveArgIndexed :: Bool+  -- ^ Argument is indexed (e.g. placed on topics of event)+  } deriving (Show, Eq, Ord)++$(deriveJSON+    (defaultOptions {fieldLabelModifier = toLowerFirst . drop 6})+    ''EventArg)++-- | Elementrary contract interface item+data Declaration+  = DConstructor { conInputs :: [FunctionArg] }+  -- ^ Contract constructor+  | DFunction { funName     :: Text+              , funConstant :: Bool+              , funInputs   :: [FunctionArg]+              , funOutputs  :: Maybe [FunctionArg] }+  -- ^ Method+  | DEvent { eveName      :: Text+           , eveInputs    :: [EventArg]+           , eveAnonymous :: Bool }+  -- ^ Event+  | DFallback { falPayable :: Bool }+  -- ^ Fallback function+  deriving Show++instance Eq Declaration where+    (DConstructor a) == (DConstructor b) = length a == length b+    (DFunction a _ _ _) == (DFunction b _ _ _) = a == b+    (DEvent a _ _) == (DEvent b _ _) = a == b+    (DFallback _) == (DFallback _) = True+    (==) _ _ = False++instance Ord Declaration where+    compare (DConstructor a) (DConstructor b) = compare (length a) (length b)+    compare (DFunction a _ _ _) (DFunction b _ _ _) = compare a b+    compare (DEvent a _ _) (DEvent b _ _) = compare a b+    compare (DFallback _) (DFallback _) = EQ++    compare DConstructor {} DFunction {} = LT+    compare DConstructor {} DEvent {} = LT+    compare DConstructor {} DFallback {} = LT++    compare DFunction {} DConstructor {} = GT+    compare DFunction {} DEvent {} = LT+    compare DFunction {} DFallback {} = LT++    compare DEvent {} DConstructor {} = GT+    compare DEvent {} DFunction {} = GT+    compare DEvent {} DFallback {} = LT++    compare DFallback {} DConstructor {} = GT+    compare DFallback {} DFunction {} = GT+    compare DFallback {} DEvent {} = GT++$(deriveJSON (defaultOptions {+    sumEncoding = TaggedObject "type" "contents"+  , constructorTagModifier = toLowerFirst . drop 1+  , fieldLabelModifier = toLowerFirst . drop 3 })+    ''Declaration)++-- | Contract Abi is a list of method / event declarations+newtype ContractAbi = ContractAbi { unAbi :: [Declaration] }+  deriving (Eq, Ord)++instance FromJSON ContractAbi where+    parseJSON = fmap ContractAbi . parseJSON++instance ToJSON ContractAbi where+    toJSON = toJSON . unAbi++instance Show ContractAbi where+    show (ContractAbi c) = T.unpack $ T.unlines $+        [ "Contract:" ]+        ++ foldMap showConstructor c +++        [ "\tEvents:" ]+        ++ foldMap showEvent c +++        [ "\tMethods:" ]+        ++ foldMap showMethod c++showConstructor :: Declaration -> [Text]+showConstructor x = case x of+    DConstructor{} -> ["\tConstructor " <> signature x]+    _              -> []++showEvent :: Declaration -> [Text]+showEvent x = case x of+    DEvent{} -> ["\t\t" <> signature x]+    _        -> []++showMethod :: Declaration -> [Text]+showMethod x = case x of+    DFunction{} ->+        ["\t\t" <> methodId x <> " " <> signature x]+    _ -> []++-- | Take a signature by given decl, e.g. foo(uint,string)+signature :: Declaration -> Text++signature (DConstructor inputs) = "(" <> args inputs <> ")"+  where+    args :: [FunctionArg] -> Text+    args = T.dropEnd 1 . foldMap (<> ",") . fmap funArgType++signature (DFallback _) = "()"++signature (DFunction name _ inputs _) = name <> "(" <> args inputs <> ")"+  where+    args :: [FunctionArg] -> Text+    args = T.dropEnd 1 . foldMap (<> ",") . fmap funArgType++signature (DEvent name inputs _) = name <> "(" <> args inputs <> ")"+  where+    args :: [EventArg] -> Text+    args = T.dropEnd 1 . foldMap (<> ",") . fmap eveArgType++-- | Localy compute Keccak-256 hash of given text+sha3 :: Text -> Text+{-# INLINE sha3 #-}+sha3 x = T.pack (show digest)+  where digest :: Digest Keccak_256+        digest = hash (encodeUtf8 x)++-- | Generate method selector by given method 'Delcaration'+methodId :: Declaration -> Text+{-# INLINE methodId #-}+methodId = ("0x" <>) . T.take 8 . sha3 . signature++-- | Generate event `topic0` hash by givent event 'Delcaration'+eventId :: Declaration -> Text+{-# INLINE eventId #-}+eventId = ("0x" <>) . sha3 . signature++-- | Solidity types and parsers+data SolidityType =+    SolidityBool+  | SolidityAddress+  | SolidityUint Int+  | SolidityInt Int+  | SolidityString+  | SolidityBytesN Int+  | SolidityBytes+  | SolidityVector [Int] SolidityType+  | SolidityArray SolidityType+    deriving (Eq, Show)++numberParser :: Parser Int+numberParser = read <$> many1 digit++parseUint :: Parser SolidityType+parseUint = do+  _ <- string "uint"+  SolidityUint <$> numberParser++parseInt :: Parser SolidityType+parseInt = do+  _ <- string "int"+  SolidityInt <$> numberParser++parseBool :: Parser SolidityType+parseBool = string "bool" >>  pure SolidityBool++parseString :: Parser SolidityType+parseString = string "string" >> pure SolidityString++parseBytes :: Parser SolidityType+parseBytes = do+  _ <- string "bytes"+  mn <- optionMaybe numberParser+  pure $ maybe SolidityBytes SolidityBytesN mn++parseAddress :: Parser SolidityType+parseAddress = string "address" >> pure SolidityAddress++solidityBasicTypeParser :: Parser SolidityType+solidityBasicTypeParser =+    choice [ try parseUint+           , try parseInt+           , try parseAddress+           , try parseBool+           , try parseString+           , parseBytes+           ]++parseVector :: Parser SolidityType+parseVector = do+    s <- solidityBasicTypeParser+    ns <- many1Till lengthParser (lookAhead (void $ string "[]") <|> eof)+    pure $ SolidityVector ns s+  where+    many1Till :: Parser Int -> Parser () -> Parser [Int]+    many1Till p end = do+      a <- p+      as <- manyTill p end+      return (a : as)++    lengthParser = do+          _ <- char '['+          n <- numberParser+          _ <- char ']'+          pure n++parseArray :: Parser SolidityType+parseArray = do+  s <- try (parseVector <* string "[]") <|> (solidityBasicTypeParser <* string "[]")+  pure $ SolidityArray s+++solidityTypeParser :: Parser SolidityType+solidityTypeParser =+    choice [ try parseArray+           , try parseVector+           , solidityBasicTypeParser+           ]++parseSolidityType :: Text -> Either ParseError SolidityType+parseSolidityType = parse solidityTypeParser "Solidity"
+ src/Language/Solidity/Compiler.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE CPP             #-}+#ifdef SOLIDITY_COMPILER+{-# LANGUAGE RecordWildCards #-}+#endif++-- |+-- Module      :  Language.Solidity.Compiler+-- Copyright   :  Alexander Krupenkin 2017+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  portable+--+-- Solidity compiler high-level bindings.+--++module Language.Solidity.Compiler where++#ifdef SOLIDITY_COMPILER++import           Data.ByteString                    (ByteString)+import           Data.Map                           (Map)+import           Data.Semigroup                     (Semigroup (..))+import qualified Language.Solidity.Compiler.Foreign as FFI+import           System.IO.Unsafe                   (unsafePerformIO)++-- | Input contract sources+data Sources = Sources+  { sourceMap    :: Map ByteString ByteString+  -- ^ Source code map from contract name in keys+  , libraries    :: Map ByteString ByteString+  -- ^ Library address map for linking+  , optimization :: Bool+  -- ^ Enable optimization?+  } deriving (Eq, Show)++instance Semigroup Sources where+    a <> b = Sources (sourceMap a `mappend` sourceMap b)+                     (libraries a `mappend` libraries b)+                     (optimization a || optimization b)++instance Monoid Sources where+    mappend = (<>)+    mempty = Sources mempty mempty False++type Compiled = Map ByteString (ByteString, ByteString)++-- | Compile Solidity contracts+compile :: Sources+        -- ^ Contract sources+        -> Either ByteString Compiled+        -- ^ Error string or compiled contracts ABI and hex+{-# NOINLINE compile #-}+compile Sources{..} = unsafePerformIO $+    FFI.compile sourceMap libraries optimization++#endif
+ src/Language/Solidity/Compiler/Foreign.hsc view
@@ -0,0 +1,106 @@+{-# LANGUAGE CPP                      #-}+{-# LANGUAGE ForeignFunctionInterface #-}++-- |+-- Module      :  Language.Solidity.Compiler.Foreign+-- Copyright   :  Alexander Krupenkin 2017+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Ethereum Solidity library FFI.+--++module Language.Solidity.Compiler.Foreign where++#ifdef SOLIDITY_COMPILER+#include <solidity_lite.h>++import Data.Map as M+import Data.ByteString.Char8 as BS+import Data.Typeable (Typeable)+import Foreign.C.String (CString, peekCString, withCString)+import Foreign.C.Types (CInt(..))+import Foreign.Ptr (Ptr)+import Foreign (free)++data Solidity+  deriving Typeable++foreign import ccall unsafe "create" c_create+    :: IO (Ptr Solidity)+foreign import ccall unsafe "destroy" c_destroy+    :: Ptr Solidity -> IO ()+foreign import ccall unsafe "addSource" c_addSource+    :: Ptr Solidity -> CString -> CString -> IO CInt+foreign import ccall unsafe "addLibrary" c_addLibrary+    :: Ptr Solidity -> CString -> CString -> IO CInt+foreign import ccall unsafe "compile" c_compile+    :: Ptr Solidity -> CInt -> IO CInt+foreign import ccall unsafe "abi" c_abi+    :: Ptr Solidity -> CString -> IO CString+foreign import ccall unsafe "binary" c_binary+    :: Ptr Solidity -> CString -> IO CString+foreign import ccall unsafe "errors" c_errors+    :: Ptr Solidity -> IO CString++withSolidity :: (Ptr Solidity -> IO a) -> IO a+{-# INLINE withSolidity #-}+withSolidity f = do+    ptr <- c_create+    r <- f ptr+    c_destroy ptr+    return r++withCStringPair :: (CString -> CString -> IO a) -> (ByteString, ByteString) -> IO a+{-# INLINE withCStringPair #-}+withCStringPair f (a, b) =+    withCString (BS.unpack a) $ \astr ->+        withCString (BS.unpack b) $ \bstr ->+            f astr bstr++addSources :: Ptr Solidity -> Map ByteString ByteString -> IO ()+{-# INLINE addSources #-}+addSources ptr = mapM_ (withCStringPair $ c_addSource ptr) . M.toList++addLibraries :: Ptr Solidity -> Map ByteString ByteString -> IO ()+{-# INLINE addLibraries #-}+addLibraries ptr = mapM_ (withCStringPair $ c_addLibrary ptr) . M.toList++result :: Ptr Solidity -> ByteString -> IO (ByteString, ByteString)+result ptr name =+    withCString (BS.unpack name) $ \cname -> do+        abi <- c_abi ptr cname+        bin <- c_binary ptr cname+        res <- (,) <$> fmap BS.pack (peekCString abi)+                   <*> fmap BS.pack (peekCString bin)+        free abi+        free bin+        return res++errors :: Ptr Solidity -> IO ByteString+errors ptr = do+    errs <- c_errors ptr+    res <- BS.pack <$> peekCString errs+    free errs+    return res++compile :: Map ByteString ByteString+        -> Map ByteString ByteString+        -> Bool+        -> IO (Either ByteString (Map ByteString (ByteString, ByteString)))+compile srcs libs opt =+    withSolidity $ \ptr -> do+        addSources ptr srcs+        addLibraries ptr libs+        res <- c_compile ptr optI+        let compiled = sequence $ M.mapWithKey (const . result ptr) srcs+        if res < 0+           then Left <$> errors ptr+           else Right <$> compiled+  where optI | opt = 1+             | otherwise = 0++#endif
− src/Network/Ethereum/ABI/Class.hs
@@ -1,71 +0,0 @@-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleContexts  #-}-{-# LANGUAGE TypeFamilies      #-}---- |--- Module      :  Network.Ethereum.ABI.Class--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI encoding base type classes.-----module Network.Ethereum.ABI.Class (-    ABIType(..)-  , ABIPut(..)-  , ABIGet(..)-  , GenericABIPut(..)-  , GenericABIGet(..)-  ) where--import           Data.Proxy     (Proxy)-import           Data.Serialize (Get, Putter)-import           Generics.SOP   (Generic, Rep, from, to)---- | A class for abi encoding datatype descriptions-class ABIType a where-    isDynamic :: Proxy a -> Bool---- | A class for encoding datatypes to their abi encoding------ If your compiler has support for the @DeriveGeneric@ and--- @DefaultSignatures@ language extensions (@ghc >= 7.2.1@),--- the 'abiPut' method will have default generic implementations.------ To use this option, simply add a @deriving 'Generic'@ clause--- to your datatype and declare a 'ABIPut' instance for it without--- giving a definition for 'abiPut'.----class ABIType a => ABIPut a where-    abiPut :: Putter a--    default abiPut :: (Generic a, Rep a ~ rep, GenericABIPut rep) => Putter a-    abiPut = gAbiPut . from---- | A class for encoding generically composed datatypes to their abi encoding-class GenericABIPut a where-    gAbiPut :: Putter a---- | A class for decoding datatypes from their abi encoding------ If your compiler has support for the @DeriveGeneric@ and--- @DefaultSignatures@ language extensions (@ghc >= 7.2.1@),--- the 'abiGet' method will have default generic implementations.------ To use this option, simply add a @deriving 'Generic'@ clause--- to your datatype and declare a 'ABIGet' instance for it without--- giving a definition for 'abiGet'.----class ABIType a => ABIGet a where-    abiGet :: Get a--    default abiGet :: (Generic a, Rep a ~ rep, GenericABIGet rep) => Get a-    abiGet = to <$> gAbiGet---- | A class for decoding generically composed datatypes from their abi encoding-class GenericABIGet a where-    gAbiGet :: Get a
− src/Network/Ethereum/ABI/Codec.hs
@@ -1,63 +0,0 @@-{-# LANGUAGE TypeFamilies #-}---- |--- Module      :  Network.Ethereum.ABI.Codec--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI encoding codec functions.-----module Network.Ethereum.ABI.Codec (-    encode-  , decode-  , encode'-  , decode'-  ) where--import           Data.ByteArray               (ByteArray, ByteArrayAccess,-                                               convert)-import           Data.Serialize               (runGet, runPut)-import           Generics.SOP                 (Generic, Rep, from, to)--import           Network.Ethereum.ABI.Class   (ABIGet (..), ABIPut (..),-                                               GenericABIGet (..),-                                               GenericABIPut (..))-import           Network.Ethereum.ABI.Generic ()---- | Encode datatype to Ethereum ABI-encoding-encode :: (ABIPut a, ByteArray ba)-       => a-       -> ba-{-# INLINE encode #-}-encode = convert . runPut . abiPut---- | Generic driven version of 'encode'-encode' :: (Generic a,-            Rep a ~ rep,-            GenericABIPut rep,-            ByteArray ba)-        => a-        -> ba-{-# INLINE encode' #-}-encode' = convert . runPut . gAbiPut . from---- | Decode datatype from Ethereum ABI-encoding-decode :: (ByteArrayAccess ba, ABIGet a)-       => ba-       -> Either String a-{-# INLINE decode #-}-decode = runGet abiGet . convert---- | Generic driven version of 'decode'-decode' :: (Generic a,-            Rep a ~ rep,-            GenericABIGet rep,-            ByteArrayAccess ba)-        => ba-        -> Either String a-decode' = runGet (to <$> gAbiGet) . convert
− src/Network/Ethereum/ABI/Event.hs
@@ -1,144 +0,0 @@-{-# LANGUAGE DataKinds              #-}-{-# LANGUAGE FlexibleContexts       #-}-{-# LANGUAGE FlexibleInstances      #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE MultiParamTypeClasses  #-}-{-# LANGUAGE PolyKinds              #-}-{-# LANGUAGE ScopedTypeVariables    #-}-{-# LANGUAGE TypeFamilies           #-}-{-# LANGUAGE TypeOperators          #-}-{-# LANGUAGE UndecidableInstances   #-}---- |--- Module      :  Network.Ethereum.Web3.Encoding.Event--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  unportable------ This module is internal, the purpose is to define--- helper classes and functions to assist in event decoding.--- The user of this library should have no need to use--- this directly in application code.-----module Network.Ethereum.ABI.Event(-    DecodeEvent(..)-  , IndexedEvent(..)-  ) where--import           Data.ByteArray                      (ByteArrayAccess)-import           Data.Proxy                          (Proxy (..))-import           Generics.SOP                        (Generic, I (..), NP (..),-                                                      NS (..), Rep, SOP (..),-                                                      from, to)--import           Network.Ethereum.ABI.Class          (GenericABIGet)-import           Network.Ethereum.ABI.Codec          (decode')-import           Network.Ethereum.ABI.Event.Internal-import           Network.Ethereum.Web3.Types         (Change (..))---- | Indexed event args come back in as a list of encoded values. 'ArrayParser'--- | is used to decode these values so that they can be used to reconstruct the--- | entire decoded event.-class ArrayParser a where-  arrayParser :: ByteArrayAccess ba-              => [ba]-              -> Either String a--instance ArrayParser (NP f '[]) where-  arrayParser _ = Right Nil--instance (ArrayParser (NP I as), Generic a, Rep a ~ rep, GenericABIGet rep)-       => ArrayParser (NP I (a : as)) where-  arrayParser [] = Left "Empty"-  arrayParser (a : as) = do-    a' <- decode' a-    as' <- arrayParser as-    return $ I a' :* as'--instance ArrayParser (NP f as) => ArrayParser (SOP f '[as]) where-  arrayParser = fmap (SOP . Z) . arrayParser--genericArrayParser :: ( Generic a-                      , Rep a ~ rep-                      , ArrayParser rep-                      , ByteArrayAccess ba-                      )-                   => [ba]-                   -> Either String a-genericArrayParser = fmap to . arrayParser------------------------------------------------------------------------------------- Event Parsing-----------------------------------------------------------------------------------data Event i ni = Event i ni---- | 'parseChange' decodes both the indexed and non-indexed event components.-parseChange :: ( Generic i-               , Rep i ~ irep-               , ArrayParser irep-               , Generic ni-               , Rep ni ~ nirep-               , GenericABIGet nirep-               )-             => Change-             -> Bool-             -- ^ is anonymous event-             -> Either String (Event i ni)-parseChange change anonymous =-    Event <$> genericArrayParser topics <*> decode' data_-  where-    topics | anonymous = changeTopics change-           | otherwise = tail (changeTopics change)-    data_ = changeData change--class IndexedEvent i ni e | e -> i ni where-  isAnonymous :: Proxy e -> Bool---- | 'CombineChange' is a class which indicates that given event components of types 'i'--- | and 'ni', we can construct an event of type 'e'. The functional dependency is valid--- | becasue of how the template haskell generates the event types.-class CombineChange i ni e | e -> i ni where-  combineChange :: i -> ni -> e--instance ( Generic i-         , Rep i ~ irep-         , Generic ni-         , Rep ni ~ nirep-         , Generic e-         , Rep e ~ erep-         , HListRep irep hli-         , HListRep nirep hlni-         , MergeIndexedArguments hli hlni-         , MergeIndexedArguments' hli hlni ~ hle-         , HListRep erep hle-         , IndexedEvent i ni e-         ) => CombineChange i ni e where-  combineChange i ni =-    let hli = toHList . from $ i-        hlni = toHList . from $ ni-        hle = mergeIndexedArguments hli hlni-    in to . fromHList $ hle--class DecodeEvent i ni e | e -> i ni where-  decodeEvent :: Change -> Either String e--instance ( IndexedEvent i ni e-         , Generic i-         , Rep i ~ SOP I '[hli]-         , Generic ni-         , Rep ni ~ SOP I '[hlni]-         , Generic e-         , Rep e ~ SOP I '[hle]-         , CombineChange i ni e-         , GenericABIGet (SOP I '[hlni])-         , ArrayParser (SOP I '[hli])-         ) => DecodeEvent i ni e where-  decodeEvent change = do-      let anonymous = isAnonymous (Proxy :: Proxy e)-      (Event i ni :: Event i ni) <- parseChange change anonymous-      return $ combineChange i ni
− src/Network/Ethereum/ABI/Event/Internal.hs
@@ -1,136 +0,0 @@-{-# LANGUAGE DataKinds              #-}-{-# LANGUAGE FlexibleContexts       #-}-{-# LANGUAGE FlexibleInstances      #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE GADTs                  #-}-{-# LANGUAGE MultiParamTypeClasses  #-}-{-# LANGUAGE PolyKinds              #-}-{-# LANGUAGE ScopedTypeVariables    #-}-{-# LANGUAGE TypeFamilies           #-}-{-# LANGUAGE TypeInType             #-}-{-# LANGUAGE TypeOperators          #-}-{-# LANGUAGE UndecidableInstances   #-}---- |--- Module      :  Network.Ethereum.ABI.Event.Internal--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  unportable------ This module is internal, the purpose is to define helper classes and types--- to assist in event decoding. The user of this library should have no need to use--- this directly in application code.-----module Network.Ethereum.ABI.Event.Internal where--import           Data.Kind    (Type)-import           Data.Proxy   (Proxy (..))-import           Data.Tagged  (Tagged (..))-import           Generics.SOP (I (..), NP (..), NS (..), SOP (..))-import           GHC.TypeLits (CmpNat)--data HList :: [Type] -> Type where-  HNil :: HList '[]-  (:<) :: a -> HList as -> HList (a : as)--infixr 0 :<---- | Generic representation to HList representation-class HListRep a xs | a -> xs, a -> xs where-  toHList :: a -> HList xs-  fromHList :: HList xs -> a--instance HListRep (NP I '[]) '[] where-  toHList _ = HNil-  fromHList _ = Nil--instance HListRep (NP I as) as => HListRep (NP I (a:as)) (a:as) where-  toHList (I a :* rest) = a :< toHList rest-  fromHList (a :< rest) = I a :* fromHList rest--instance HListRep (NP f as') as => HListRep (SOP f '[as']) as where-  toHList (SOP (Z rep)) = toHList rep-  toHList _             = error "Impossible branch"-  fromHList = SOP . Z . fromHList---- | Sort a Tagged HList-class Sort (xs :: [Type]) where-  type Sort' xs :: [Type]-  sort :: HList xs -> HList (Sort' xs)--instance Sort '[] where-  type Sort' '[] = '[]-  sort HNil = HNil--instance (Sort xs, Insert x (Sort' xs)) => Sort (x : xs) where-  type Sort' (x : xs) = Insert' x (Sort' xs)-  sort (x :< xs) = insert x (sort xs)--class Insert (x :: Type) (xs :: [Type]) where-  type Insert' x xs :: [Type]-  insert :: x -> HList xs -> HList (Insert' x xs)--instance Insert x '[] where-  type Insert' x '[] = '[x]-  insert x HNil = x :< HNil--instance InsertCmp (CmpNat n m) (Tagged n x) (Tagged m y) ys => Insert (Tagged n x) (Tagged m y : ys) where-  type Insert' (Tagged n x) (Tagged m y : ys) = InsertCmp' (CmpNat n m) (Tagged n x) (Tagged m y) ys-  insert (x :: Tagged n x) ((y :: Tagged m y) :< ys) = insertCmp (Proxy :: Proxy (CmpNat n m)) x y ys--class InsertCmp (b :: Ordering) (x :: Type) (y :: Type) (ys :: [Type]) where-  type InsertCmp' b x y ys :: [Type]-  insertCmp :: Proxy (b :: Ordering) -> x -> y -> HList ys -> HList (InsertCmp' b x y ys)--instance InsertCmp 'LT x y ys where-  type InsertCmp' 'LT x y ys = x : (y : ys)-  insertCmp _ x y ys = x :< y :< ys--instance Insert x ys => InsertCmp 'GT x y ys where-  type InsertCmp' 'GT x y ys = y : Insert' x ys-  insertCmp _ x y ys = y :< insert x ys---- | Unwrap all the Tagged items in an HList-class UnTag t where-  type UnTag' t :: [Type]-  unTag :: HList t -> HList (UnTag' t)--instance UnTag '[] where-  type UnTag' '[] = '[]-  unTag a = a--instance UnTag ts => UnTag (Tagged n a : ts) where-  type UnTag' (Tagged n a : ts) = a : UnTag' ts-  unTag (Tagged a :< ts) = a :< unTag ts--class HListMerge (as :: [Type]) (bs :: [Type]) where-  type Concat as bs :: [Type]-  mergeHList :: HList as -> HList bs -> HList (Concat as bs)--instance HListMerge '[] bs where-  type Concat '[] bs = bs-  mergeHList _ bs = bs--instance HListMerge as bs => HListMerge (a : as) bs where-  type Concat (a : as) bs = a : Concat as bs-  mergeHList (a :< as) bs = a :< mergeHList as bs--class HListMergeSort as bs where-  type MergeSort' as bs :: [Type]-  mergeSortHList :: HList as -> HList bs -> HList (MergeSort' as bs)--instance (HListMerge as bs, Concat as bs ~ cs, Sort cs, Sort' cs ~ cs') => HListMergeSort as bs where-  type MergeSort' as bs = Sort' (Concat as bs)-  mergeSortHList as bs = sort $ (mergeHList as bs :: HList cs)--class MergeIndexedArguments as bs where-  type MergeIndexedArguments' as bs :: [Type]-  mergeIndexedArguments :: HList as -> HList bs -> HList (MergeIndexedArguments' as bs)--instance (HListMergeSort as bs, MergeSort' as bs ~ cs, UnTag cs, UnTag cs' ~ ds) => MergeIndexedArguments as bs where-  type MergeIndexedArguments' as bs = (UnTag' (MergeSort' as bs))-  mergeIndexedArguments as bs = unTag $ mergeSortHList as bs
− src/Network/Ethereum/ABI/Generic.hs
@@ -1,126 +0,0 @@-{-# LANGUAGE DataKinds           #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE RecordWildCards     #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE TypeInType          #-}-{-# LANGUAGE TypeOperators       #-}---- |--- Module      :  Network.Ethereum.ABI.Generic--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ This module is internal, the purpose is to define helper classes and functions--- to assist in encoding and decoding Solidity types for function calls and events.--- The user of this library should have no need to use this directly in application code.-----module Network.Ethereum.ABI.Generic () where--import qualified Data.ByteString.Lazy          as LBS-import           Data.Int                      (Int64)-import qualified Data.List                     as L-import           Data.Monoid                   ((<>))-import           Data.Proxy                    (Proxy (..))-import           Data.Serialize                (Get, Put)-import           Data.Serialize.Get            (bytesRead, lookAheadE, skip)-import           Data.Serialize.Put            (runPutLazy)-import           Generics.SOP                  (I (..), NP (..), NS (..),-                                                SOP (..))--import           Network.Ethereum.ABI.Class    (ABIGet (..), ABIPut (..),-                                                ABIType (..),-                                                GenericABIGet (..),-                                                GenericABIPut (..))-import           Network.Ethereum.ABI.Prim.Int (getWord256, putWord256)--data EncodedValue =-  EncodedValue { order    :: Int64-               , offset   :: Maybe Int64-               , encoding :: Put-               }--instance Eq EncodedValue where-  ev1 == ev2 = order ev1 == order ev2--instance Ord EncodedValue where-  compare ev1 ev2 = order ev1 `compare` order ev2--combineEncodedValues :: [EncodedValue] -> Put-combineEncodedValues encodings =-  let sortedEs = adjust headsOffset $ L.sort encodings-      encodings' = addTailOffsets headsOffset [] sortedEs-  in let heads = foldl (\acc EncodedValue{..} -> case offset of-                          Nothing -> acc <> encoding-                          Just o  -> acc <> putWord256 (fromIntegral o)-                      ) mempty encodings'-         tails = foldl (\acc EncodedValue{..} -> case offset of-                          Nothing -> acc-                          Just _  -> acc <> encoding-                      ) mempty encodings'-      in heads <> tails-  where-    adjust :: Int64 -> [EncodedValue] -> [EncodedValue]-    adjust n = map (\ev -> ev {offset = (+) n <$> offset ev})-    addTailOffsets :: Int64 -> [EncodedValue] -> [EncodedValue] -> [EncodedValue]-    addTailOffsets init' acc es = case es of-      [] -> reverse acc-      (e : tail') -> case offset e of-        Nothing -> addTailOffsets init' (e : acc) tail'-        Just _  -> addTailOffsets init' (e : acc) (adjust (LBS.length . runPutLazy . encoding $ e) tail')-    headsOffset :: Int64-    headsOffset = foldl (\acc e -> case offset e of-                                Nothing -> acc + (LBS.length . runPutLazy . encoding $ e)-                                Just _ -> acc + 32-                            ) 0 encodings--class ABIData a where-    _serialize :: [EncodedValue] -> a -> [EncodedValue]--instance ABIData (NP f '[]) where-    _serialize encoded _ = encoded--instance (ABIType b, ABIPut b, ABIData (NP I as)) => ABIData (NP I (b :as)) where-    _serialize encoded (I b :* a) =-        if isDynamic (Proxy :: Proxy b)-        then _serialize (dynEncoding  : encoded) a-        else _serialize (staticEncoding : encoded) a-      where-        staticEncoding = EncodedValue { encoding = abiPut b-                                      , offset = Nothing-                                      , order = 1 + (fromInteger . toInteger . L.length $ encoded)-                                      }-        dynEncoding = EncodedValue { encoding = abiPut b-                                   , offset = Just 0-                                   , order = 1 + (fromInteger . toInteger . L.length $ encoded)-                                   }--instance ABIData (NP f as) => GenericABIPut (SOP f '[as]) where-    gAbiPut (SOP (Z a)) = combineEncodedValues $ _serialize [] a-    gAbiPut _           = error "Impossible branch"--instance GenericABIGet (NP f '[]) where-    gAbiGet = return Nil--instance (ABIGet a, GenericABIGet (NP I as)) => GenericABIGet (NP I (a : as)) where-    gAbiGet = (:*) <$> (I <$> factorParser) <*> gAbiGet--instance GenericABIGet (NP f as) => GenericABIGet (SOP f '[as]) where-    gAbiGet = SOP . Z <$> gAbiGet--factorParser :: forall a . ABIGet a => Get a-factorParser-  | not $ isDynamic (Proxy :: Proxy a) = abiGet-  | otherwise = do-        dataOffset <- fromIntegral <$> getWord256-        currentOffset <- bytesRead-        Left x <- lookAheadE $ do-            skip (dataOffset - currentOffset)-            Left <$> abiGet-        return x
− src/Network/Ethereum/ABI/Json.hs
@@ -1,280 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell   #-}---- |--- Module      :  Network.Ethereum.ABI.Json--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ JSON encoded contract ABI parsers.-----module Network.Ethereum.ABI.Json (-    ContractABI(..)-  , Declaration(..)-  , FunctionArg(..)-  , EventArg(..)-  , signature-  , methodId-  , eventId-  , SolidityType(..)-  , parseSolidityType-  ) where--import           Control.Monad      (void)-import           Crypto.Hash        (Digest, Keccak_256, hash)-import           Data.Aeson         (FromJSON (parseJSON), Options (constructorTagModifier, fieldLabelModifier, sumEncoding),-                                     SumEncoding (TaggedObject),-                                     ToJSON (toJSON), defaultOptions)-import           Data.Aeson.TH      (deriveJSON)-import           Data.Monoid        ((<>))-import           Data.Text          (Text)-import qualified Data.Text          as T (dropEnd, pack, take, unlines, unpack)-import           Data.Text.Encoding (encodeUtf8)-import           Text.Parsec        (ParseError, char, choice, digit, eof,-                                     lookAhead, many1, manyTill, optionMaybe,-                                     parse, string, try, (<|>))-import           Text.Parsec.Text   (Parser)--import           Data.String.Extra  (toLowerFirst)---- | Method argument-data FunctionArg = FunctionArg-  { funArgName :: Text-  -- ^ Argument name-  , funArgType :: Text-  -- ^ Argument type-  } deriving (Show, Eq, Ord)--$(deriveJSON-    (defaultOptions {fieldLabelModifier = toLowerFirst . drop 6})-    ''FunctionArg)---- | Event argument-data EventArg = EventArg-  { eveArgName    :: Text-  -- ^ Argument name-  , eveArgType    :: Text-  -- ^ Argument type-  , eveArgIndexed :: Bool-  -- ^ Argument is indexed (e.g. placed on topics of event)-  } deriving (Show, Eq, Ord)--$(deriveJSON-    (defaultOptions {fieldLabelModifier = toLowerFirst . drop 6})-    ''EventArg)---- | Elementrary contract interface item-data Declaration-  = DConstructor { conInputs :: [FunctionArg] }-  -- ^ Contract constructor-  | DFunction { funName     :: Text-              , funConstant :: Bool-              , funInputs   :: [FunctionArg]-              , funOutputs  :: Maybe [FunctionArg] }-  -- ^ Method-  | DEvent { eveName      :: Text-           , eveInputs    :: [EventArg]-           , eveAnonymous :: Bool }-  -- ^ Event-  | DFallback { falPayable :: Bool }-  -- ^ Fallback function-  deriving Show--instance Eq Declaration where-    (DConstructor a) == (DConstructor b) = length a == length b-    (DFunction a _ _ _) == (DFunction b _ _ _) = a == b-    (DEvent a _ _) == (DEvent b _ _) = a == b-    (DFallback _) == (DFallback _) = True-    (==) _ _ = False--instance Ord Declaration where-    compare (DConstructor a) (DConstructor b) = compare (length a) (length b)-    compare (DFunction a _ _ _) (DFunction b _ _ _) = compare a b-    compare (DEvent a _ _) (DEvent b _ _) = compare a b-    compare (DFallback _) (DFallback _) = EQ--    compare DConstructor {} DFunction {} = LT-    compare DConstructor {} DEvent {} = LT-    compare DConstructor {} DFallback {} = LT--    compare DFunction {} DConstructor {} = GT-    compare DFunction {} DEvent {} = LT-    compare DFunction {} DFallback {} = LT--    compare DEvent {} DConstructor {} = GT-    compare DEvent {} DFunction {} = GT-    compare DEvent {} DFallback {} = LT--    compare DFallback {} DConstructor {} = GT-    compare DFallback {} DFunction {} = GT-    compare DFallback {} DEvent {} = GT--$(deriveJSON (defaultOptions {-    sumEncoding = TaggedObject "type" "contents"-  , constructorTagModifier = toLowerFirst . drop 1-  , fieldLabelModifier = toLowerFirst . drop 3 })-    ''Declaration)---- | Contract ABI is a list of method / event declarations-newtype ContractABI = ContractABI { unABI :: [Declaration] }-  deriving (Eq, Ord)--instance FromJSON ContractABI where-    parseJSON = fmap ContractABI . parseJSON--instance ToJSON ContractABI where-    toJSON = toJSON . unABI--instance Show ContractABI where-    show (ContractABI c) = T.unpack $ T.unlines $-        [ "Contract:" ]-        ++ foldMap showConstructor c ++-        [ "\tEvents:" ]-        ++ foldMap showEvent c ++-        [ "\tMethods:" ]-        ++ foldMap showMethod c--showConstructor :: Declaration -> [Text]-showConstructor x = case x of-    DConstructor{} -> ["\tConstructor " <> signature x]-    _              -> []--showEvent :: Declaration -> [Text]-showEvent x = case x of-    DEvent{} -> ["\t\t" <> signature x]-    _        -> []--showMethod :: Declaration -> [Text]-showMethod x = case x of-    DFunction{} ->-        ["\t\t" <> methodId x <> " " <> signature x]-    _ -> []---- | Take a signature by given decl, e.g. foo(uint,string)-signature :: Declaration -> Text--signature (DConstructor inputs) = "(" <> args inputs <> ")"-  where-    args :: [FunctionArg] -> Text-    args = T.dropEnd 1 . foldMap (<> ",") . fmap funArgType--signature (DFallback _) = "()"--signature (DFunction name _ inputs _) = name <> "(" <> args inputs <> ")"-  where-    args :: [FunctionArg] -> Text-    args = T.dropEnd 1 . foldMap (<> ",") . fmap funArgType--signature (DEvent name inputs _) = name <> "(" <> args inputs <> ")"-  where-    args :: [EventArg] -> Text-    args = T.dropEnd 1 . foldMap (<> ",") . fmap eveArgType---- | Localy compute Keccak-256 hash of given text-sha3 :: Text -> Text-{-# INLINE sha3 #-}-sha3 x = T.pack (show digest)-  where digest :: Digest Keccak_256-        digest = hash (encodeUtf8 x)---- | Generate method selector by given method 'Delcaration'-methodId :: Declaration -> Text-{-# INLINE methodId #-}-methodId = ("0x" <>) . T.take 8 . sha3 . signature---- | Generate event `topic0` hash by givent event 'Delcaration'-eventId :: Declaration -> Text-{-# INLINE eventId #-}-eventId = ("0x" <>) . sha3 . signature---- | Solidity types and parsers-data SolidityType =-    SolidityBool-  | SolidityAddress-  | SolidityUint Int-  | SolidityInt Int-  | SolidityString-  | SolidityBytesN Int-  | SolidityBytes-  | SolidityVector [Int] SolidityType-  | SolidityArray SolidityType-    deriving (Eq, Show)--numberParser :: Parser Int-numberParser = read <$> many1 digit--parseUint :: Parser SolidityType-parseUint = do-  _ <- string "uint"-  n <- numberParser-  pure $ SolidityUint n--parseInt :: Parser SolidityType-parseInt = do-  _ <- string "int"-  n <- numberParser-  pure $ SolidityInt n--parseBool :: Parser SolidityType-parseBool = string "bool" >>  pure SolidityBool--parseString :: Parser SolidityType-parseString = string "string" >> pure SolidityString--parseBytes :: Parser SolidityType-parseBytes = do-  _ <- string "bytes"-  mn <- optionMaybe numberParser-  pure $ maybe SolidityBytes SolidityBytesN mn--parseAddress :: Parser SolidityType-parseAddress = string "address" >> pure SolidityAddress--solidityBasicTypeParser :: Parser SolidityType-solidityBasicTypeParser =-    choice [ try parseUint-           , try parseInt-           , try parseAddress-           , try parseBool-           , try parseString-           , parseBytes-           ]--parseVector :: Parser SolidityType-parseVector = do-    s <- solidityBasicTypeParser-    ns <- many1Till lengthParser ((lookAhead $ void (string "[]")) <|> eof)-    pure $ SolidityVector ns s-  where-    many1Till :: Parser Int -> Parser () -> Parser [Int]-    many1Till p end = do-      a <- p-      as <- manyTill p end-      return (a : as)--    lengthParser = do-          _ <- char '['-          n <- numberParser-          _ <- char ']'-          pure n--parseArray :: Parser SolidityType-parseArray = do-  s <- (try $ parseVector <* string "[]") <|> (solidityBasicTypeParser <* string "[]")-  pure $ SolidityArray s---solidityTypeParser :: Parser SolidityType-solidityTypeParser =-    choice [ try parseArray-           , try parseVector-           , solidityBasicTypeParser-           ]--parseSolidityType :: Text -> Either ParseError SolidityType-parseSolidityType = parse solidityTypeParser "Solidity"
− src/Network/Ethereum/ABI/Prim.hs
@@ -1,30 +0,0 @@--- |--- Module      :  Network.Ethereum.ABI.Prim--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI encoding primitive types.-----module Network.Ethereum.ABI.Prim (-    Address-  , Bytes-  , BytesN-  , IntN-  , UIntN-  , ListN-  , Singleton(..)-  ) where--import           Network.Ethereum.ABI.Prim.Address (Address)-import           Network.Ethereum.ABI.Prim.Bool    ()-import           Network.Ethereum.ABI.Prim.Bytes   (Bytes, BytesN)-import           Network.Ethereum.ABI.Prim.Int     (IntN, UIntN)-import           Network.Ethereum.ABI.Prim.List    (ListN)-import           Network.Ethereum.ABI.Prim.String  ()-import           Network.Ethereum.ABI.Prim.Tagged  ()-import           Network.Ethereum.ABI.Prim.Tuple   (Singleton (..))
− src/Network/Ethereum/ABI/Prim/Address.hs
@@ -1,81 +0,0 @@-{-# LANGUAGE DataKinds         #-}-{-# LANGUAGE DeriveGeneric     #-}-{-# LANGUAGE OverloadedStrings #-}---- |--- Module      :  Network.Ethereum.ABI.Prim.Address--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI address type.-----module Network.Ethereum.ABI.Prim.Address (-    Address-  ) where--import           Control.Monad                 ((<=<))-import           Data.Aeson                    (FromJSON (..), ToJSON (..),-                                                Value (String))-import           Data.ByteArray                (Bytes, zero)-import           Data.ByteArray.Encoding       (Base (Base16), convertFromBase,-                                                convertToBase)-import           Data.ByteString               (ByteString)-import qualified Data.ByteString.Char8         as C8 (drop, pack, take, unpack)-import           Data.Monoid                   ((<>))-import           Data.String                   (IsString (..))-import           Data.Text.Encoding            (decodeUtf8, encodeUtf8)-import           Generics.SOP                  (Generic)-import qualified GHC.Generics                  as GHC (Generic)--import           Network.Ethereum.ABI.Class    (ABIGet (..), ABIPut (..),-                                                ABIType (..))-import           Network.Ethereum.ABI.Codec    (decode, encode)-import           Network.Ethereum.ABI.Prim.Int (UIntN)---- | Ethereum account address-newtype Address = Address { unAddress :: UIntN 160 }-  deriving (Eq, Ord, GHC.Generic)--instance Generic Address---- TODO: Address . drop 12 . sha3-{--fromPublic :: ByteArrayAccess bin => bin -> Maybe Address-fromPublic = undefined--}--fromHexString :: ByteString -> Either String Address-fromHexString = decode . align <=< convertFromBase Base16 . trim0x-  where trim0x s | C8.take 2 s == "0x" = C8.drop 2 s-                 | otherwise = s-        align = (zero 12 <>) :: Bytes -> Bytes--toHexString :: Address -> ByteString-toHexString = ("0x" <>) . convertToBase Base16 . C8.drop 12 . encode--instance Show Address where-    show = C8.unpack . toHexString--instance IsString Address where-    fromString = either error id . fromHexString . C8.pack--instance ABIType Address where-    isDynamic _ = False--instance ABIGet Address where-    abiGet = Address <$> abiGet--instance ABIPut Address where-    abiPut = abiPut . unAddress--instance FromJSON Address where-    parseJSON (String a) = either fail return $ fromHexString (encodeUtf8 a)-    parseJSON _          = fail "Address should be a string"--instance ToJSON Address where-    toJSON = String . decodeUtf8 . toHexString
− src/Network/Ethereum/ABI/Prim/Bool.hs
@@ -1,29 +0,0 @@-{-# LANGUAGE DeriveGeneric              #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}---- |--- Module      :  Network.Ethereum.ABI.Prim.Bool--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI boolean type.-----module Network.Ethereum.ABI.Prim.Bool () where--import           Network.Ethereum.ABI.Class    (ABIGet (..), ABIPut (..),-                                                ABIType (..))-import           Network.Ethereum.ABI.Prim.Int (getWord256, putWord256)--instance ABIType Bool where-    isDynamic _ = False--instance ABIGet Bool where-    abiGet = toEnum . fromIntegral <$> getWord256--instance ABIPut Bool where-    abiPut = putWord256 . fromIntegral . fromEnum
− src/Network/Ethereum/ABI/Prim/Bytes.hs
@@ -1,118 +0,0 @@-{-# LANGUAGE DataKinds           #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE TypeOperators       #-}---- |--- Module      :  Network.Ethereum.ABI.Prim.Bytes--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI bytes and bytesN types.-----module Network.Ethereum.ABI.Prim.Bytes (-    Bytes-  , BytesN-  ) where--import           Data.Aeson                    (FromJSON (..), ToJSON (..),-                                                Value (String))-import           Data.ByteArray                (Bytes, convert, length, zero)-import           Data.ByteArray.Encoding       (Base (Base16), convertFromBase,-                                                convertToBase)-import           Data.ByteArray.Sized          (SizedByteArray,-                                                unSizedByteArray,-                                                unsafeFromByteArrayAccess)-import qualified Data.ByteArray.Sized          as S (take)-import           Data.ByteString               (ByteString)-import qualified Data.ByteString.Char8         as C8-import           Data.Monoid                   ((<>))-import           Data.Proxy                    (Proxy (..))-import           Data.Serialize                (Get, Putter, getBytes,-                                                putByteString)-import           Data.String                   (IsString (..))-import qualified Data.Text                     as T (append, drop, take)-import           Data.Text.Encoding            (decodeUtf8, encodeUtf8)-import           GHC.TypeLits-import           Prelude                       hiding (length)--import           Network.Ethereum.ABI.Class    (ABIGet (..), ABIPut (..),-                                                ABIType (..))-import           Network.Ethereum.ABI.Prim.Int (getWord256, putWord256)--instance ABIType ByteString where-    isDynamic _ = True--instance ABIGet ByteString where-    abiGet = abiGetByteString--instance ABIPut ByteString where-    abiPut = abiPutByteString--instance ABIType Bytes where-    isDynamic _ = True--instance ABIGet Bytes where-    abiGet = convert <$> abiGetByteString--instance ABIPut Bytes where-    abiPut = abiPutByteString . convert--instance IsString Bytes where-    fromString ('0' : 'x' : hex) = either error id $ convertFromBase Base16 (C8.pack hex)-    fromString str               = convert (C8.pack str)--instance FromJSON Bytes where-    parseJSON (String hex)-        | T.take 2 hex == "0x" =-            either fail pure $ convertFromBase Base16 $ encodeUtf8 $ T.drop 2 hex-        | otherwise = fail "Hex string should have '0x' prefix"-    parseJSON _ = fail "Bytes should be encoded as hex string"--instance ToJSON Bytes where-    toJSON = toJSON . T.append "0x" . decodeUtf8 . convertToBase Base16--type BytesN n = SizedByteArray n Bytes--instance (n <= 32) => ABIType (BytesN n) where-    isDynamic _ = False--instance (KnownNat n, n <= 32) => ABIGet (BytesN n) where-    abiGet = do-        ba <- unsafeFromByteArrayAccess <$> getBytes 32-        return $ S.take (ba :: BytesN 32)--instance (KnownNat n, n <= 32) => ABIPut (BytesN n) where-    abiPut ba = putByteString $ convert ba <> zero (32 - len)-      where len = fromIntegral $ natVal (Proxy :: Proxy n)--instance (KnownNat n, n <= 32) => IsString (BytesN n) where-    fromString = unsafeFromByteArrayAccess . (fromString :: String -> Bytes)--instance (KnownNat n, n <= 32) => FromJSON (BytesN n) where-    parseJSON v = do ba <- parseJSON v-                     return $ unsafeFromByteArrayAccess (ba :: Bytes)--instance (KnownNat n, n <= 32) => ToJSON (BytesN n) where-    toJSON ba = toJSON (unSizedByteArray ba :: Bytes)--abiGetByteString :: Get ByteString-abiGetByteString = do-    len <- fromIntegral <$> getWord256-    ba <- getBytes len-    _ <- getBytes $ 32 - len `mod` 32-    return ba--abiPutByteString :: Putter ByteString-abiPutByteString bs = do-    putWord256 $ fromIntegral len-    putByteString $ bs <> zero (32 - len `mod` 32)-  where len = length bs
− src/Network/Ethereum/ABI/Prim/Int.hs
@@ -1,119 +0,0 @@-{-# LANGUAGE DataKinds                  #-}-{-# LANGUAGE DeriveGeneric              #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE KindSignatures             #-}-{-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE TypeOperators              #-}---- |--- Module      :  Network.Ethereum.Encoding.Prim.Int--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI intN and uintN types.-----module Network.Ethereum.ABI.Prim.Int (-    IntN-  , UIntN-  , getWord256-  , putWord256-  ) where--import qualified Basement.Numerical.Number  as Basement (toInteger)-import           Basement.Types.Word256     (Word256 (Word256))-import qualified Basement.Types.Word256     as Basement (quot, rem)-import           Data.Bits                  (Bits (testBit))-import           Data.Proxy                 (Proxy (..))-import           Data.Serialize             (Get, Putter, Serialize (get, put))-import           GHC.Generics               (Generic)-import           GHC.TypeLits--import           Network.Ethereum.ABI.Class (ABIGet (..), ABIPut (..),-                                             ABIType (..))--instance Real Word256 where-    toRational = toRational . toInteger--instance Integral Word256 where-    toInteger = Basement.toInteger-    quotRem a b = (Basement.quot a b, Basement.rem a b)--newtype UIntN (n :: Nat) = UIntN { unUIntN :: Word256 }-    deriving (Eq, Ord, Enum, Num, Bits, Generic)--instance (KnownNat n, n <= 256) => Show (UIntN n) where-    show = show . unUIntN--instance (KnownNat n, n <= 256) => Bounded (UIntN n) where-    minBound = 0-    maxBound = 2 ^ (natVal (Proxy :: Proxy n)) - 1--instance (KnownNat n, n <= 256) => Real (UIntN n) where-    toRational = toRational . toInteger--instance (KnownNat n, n <= 256) => Integral (UIntN n) where-    toInteger = toInteger . unUIntN-    quotRem (UIntN a) (UIntN b) = (UIntN $ quot a b, UIntN $ rem a b)--instance (n <= 256) => ABIType (UIntN n) where-    isDynamic _ = False--instance (n <= 256) => ABIGet (UIntN n) where-    abiGet = UIntN <$> getWord256--instance (n <= 256) => ABIPut (UIntN n) where-    abiPut = putWord256 . unUIntN---- TODO: Signed data type-newtype IntN (n :: Nat) = IntN { unIntN :: Word256 }-    deriving (Eq, Ord, Enum, Bits, Generic)--instance (KnownNat n, n <= 256) => Show (IntN n) where-    show = show . toInteger--instance (KnownNat n, n <= 256) => Bounded (IntN n) where-    minBound = negate $ 2 ^ (natVal (Proxy :: Proxy (n :: Nat)) - 1)-    maxBound = 2 ^ (natVal (Proxy :: Proxy (n :: Nat)) - 1) - 1--instance (KnownNat n, n <= 256) => Num (IntN n) where-    a + b  = fromInteger (toInteger a + toInteger b)-    a - b  = fromInteger (toInteger a - toInteger b)-    a * b  = fromInteger (toInteger a * toInteger b)-    abs    = fromInteger . abs . toInteger-    negate = fromInteger . negate . toInteger-    signum = fromInteger . signum . toInteger-    fromInteger x-      | x >= 0 = IntN (fromInteger x)-      | otherwise = IntN (fromInteger $ 2 ^ 256 + x)--instance (KnownNat n, n <= 256) => Real (IntN n) where-    toRational = toRational . toInteger--instance (KnownNat n, n <= 256) => Integral (IntN n) where-    quotRem (IntN a) (IntN b) = (IntN $ quot a b, IntN $ rem a b)-    toInteger x-      | testBit x 255 = toInteger (unIntN x) - 2 ^ 256-      | otherwise = toInteger $ unIntN x--instance (n <= 256) => ABIType (IntN n) where-    isDynamic _ = False--instance (n <= 256) => ABIGet (IntN n) where-    abiGet = IntN <$> getWord256--instance (n <= 256) => ABIPut (IntN n) where-    abiPut = putWord256 . unIntN--putWord256 :: Putter Word256-putWord256 (Word256 a3 a2 a1 a0) =-    put a3 >> put a2 >> put a1 >> put a0--getWord256 :: Get Word256-getWord256 = Word256 <$> get <*> get <*> get <*> get
− src/Network/Ethereum/ABI/Prim/List.hs
@@ -1,55 +0,0 @@-{-# LANGUAGE FlexibleContexts     #-}-{-# LANGUAGE TypeFamilies         #-}-{-# LANGUAGE UndecidableInstances #-}---- |--- Module      :  Network.Ethereum.ABI.Prim.List--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI dynamic and static size vectors based on linked lists.-----module Network.Ethereum.ABI.Prim.List (-    ListN-  ) where--import           Basement.Nat                  (NatWithinBound)-import           Basement.Sized.List           (ListN, toListN_, unListN)-import qualified Basement.Sized.List           as SL (mapM_, replicateM)-import           Control.Monad                 (replicateM)-import           GHC.Exts                      (IsList (..))-import           GHC.TypeLits                  (KnownNat)--import           Network.Ethereum.ABI.Class    (ABIGet (..), ABIPut (..),-                                                ABIType (..))-import           Network.Ethereum.ABI.Prim.Int (getWord256, putWord256)--instance ABIType [a] where-    isDynamic _ = True--instance ABIPut a => ABIPut [a] where-    abiPut l = do putWord256 $ fromIntegral (length l)-                  foldMap abiPut l--instance ABIGet a => ABIGet [a] where-    abiGet = do len <- fromIntegral <$> getWord256-                replicateM len abiGet--instance ABIType (ListN n a) where-    isDynamic _ = False--instance ABIPut a => ABIPut (ListN n a) where-    abiPut = SL.mapM_ abiPut--instance (NatWithinBound Int n, KnownNat n, ABIGet a) => ABIGet (ListN n a) where-    abiGet = SL.replicateM abiGet--instance (NatWithinBound Int n, KnownNat n) => IsList (ListN n a) where-    type Item (ListN n a) = a-    fromList = toListN_-    toList   = unListN
− src/Network/Ethereum/ABI/Prim/String.hs
@@ -1,29 +0,0 @@--- |--- Module      :  Network.Ethereum.ABI.Prim.String--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI UTF8-encoded string type.-----module Network.Ethereum.ABI.Prim.String () where--import           Data.Text                       (Text)-import           Data.Text.Encoding              (decodeUtf8, encodeUtf8)--import           Network.Ethereum.ABI.Class      (ABIGet (..), ABIPut (..),-                                                  ABIType (..))-import           Network.Ethereum.ABI.Prim.Bytes ()--instance ABIType Text where-    isDynamic _ = True--instance ABIPut Text where-    abiPut = abiPut . encodeUtf8--instance ABIGet Text where-    abiGet = decodeUtf8 <$> abiGet
− src/Network/Ethereum/ABI/Prim/Tagged.hs
@@ -1,36 +0,0 @@-{-# LANGUAGE PolyKinds           #-}-{-# LANGUAGE ScopedTypeVariables #-}---- |--- Module      :  Network.Ethereum.ABI.Prim.Tagged--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Ethereum ABI UTF8-encoded tagged types.-----module Network.Ethereum.ABI.Prim.Tagged (-    Tagged-  ) where--import           Data.Proxy                 (Proxy (..))-import           Data.Tagged                (Tagged (..))-import           Generics.SOP               (Generic)--import           Network.Ethereum.ABI.Class (ABIGet (..), ABIPut (..),-                                             ABIType (..))--instance ABIType a => ABIType (Tagged t a) where-    isDynamic _ = isDynamic (Proxy :: Proxy a)--instance ABIPut a => ABIPut (Tagged t a) where-    abiPut (Tagged a) = abiPut a--instance ABIGet a => ABIGet (Tagged t a) where-    abiGet = Tagged <$> abiGet--instance Generic a => Generic (Tagged t a)
− src/Network/Ethereum/ABI/Prim/Tuple.hs
@@ -1,45 +0,0 @@-{-# LANGUAGE DeriveGeneric       #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving  #-}-{-# LANGUAGE TemplateHaskell     #-}---- |--- Module      :  Network.Ethereum.ABI.Prim.Tuple--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ Tuple type abi encoding instances.-----module Network.Ethereum.ABI.Prim.Tuple (-    Singleton(..)-  ) where--import           Data.Proxy                         (Proxy (..))-import           Generics.SOP                       (Generic)-import qualified GHC.Generics                       as GHC (Generic)--import           Network.Ethereum.ABI.Class         (ABIGet, ABIPut,-                                                     ABIType (..))-import           Network.Ethereum.ABI.Generic       ()-import           Network.Ethereum.ABI.Prim.Tuple.TH (tupleDecs)---- | The type for one-tuples-newtype Singleton a = Singleton { unSingleton :: a }-  deriving GHC.Generic--deriving instance Eq a => Eq (Singleton a)-deriving instance Show a => Show (Singleton a)-instance Generic (Singleton a)--instance ABIType a => ABIType (Singleton a) where-    isDynamic _ = isDynamic (Proxy :: Proxy a)--instance ABIGet a => ABIGet (Singleton a)-instance ABIPut a => ABIPut (Singleton a)--$(fmap concat $ sequence $ map tupleDecs [2..20])
− src/Network/Ethereum/ABI/Prim/Tuple/TH.hs
@@ -1,34 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}---- |--- Module      :  Network.Ethereum.ABI.Prim.Tuple.TH--- Copyright   :  Alexander Krupenkin 2016-2018--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  noportable------ This module is for internal usage only.--- It contains tuple abi encoding template haskell generator.-----module Network.Ethereum.ABI.Prim.Tuple.TH (tupleDecs) where---import           Control.Monad              (replicateM)-import           Language.Haskell.TH        (DecsQ, Type (VarT), appT, clause,-                                             conT, cxt, funD, instanceD,-                                             newName, normalB, tupleT)--import           Network.Ethereum.ABI.Class (ABIGet, ABIPut, ABIType (..))--tupleDecs :: Int -> DecsQ-tupleDecs n = do-    vars <- replicateM n $ newName "a"-    let types = fmap (pure . VarT) vars-    sequence $-      [ instanceD (cxt $ map (appT $ conT ''ABIType) types) (appT (conT ''ABIType) (foldl appT (tupleT n) types))-          [funD 'isDynamic [clause [] (normalB [|const False|]) []]]-      , instanceD (cxt $ map (appT $ conT ''ABIGet) types) (appT (conT ''ABIGet) (foldl appT (tupleT n) types)) []-      , instanceD (cxt $ map (appT $ conT ''ABIPut) types) (appT (conT ''ABIPut) (foldl appT (tupleT n) types)) [] ]
+ src/Network/Ethereum/Account.hs view
@@ -0,0 +1,54 @@+-- |+-- Module      :  Network.Ethereum.Account+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- In Etereun there are two types of accounts:+-- * Externally owned account (EOAs): an account controlled by a private key, and if you own the private key associated with the EOA you have the ability to send ether and messages from it.+-- * Contract: an account that has its own code, and is controlled by code.+--+-- This module exports different kinds of EOAs: default, node managed and local. Node managed accounts+-- use 'Personal' JSON-RPC API for signing transactions. Local account sign transaction locally and+-- use 'sendRawTransaction' method to export transaction to Ethereum network.+--++module Network.Ethereum.Account+    (+    -- * The @Account@ type+      Account(..)++    -- * Default node account+    , DefaultAccount++    -- * Unlockable node account+    , PersonalAccount+    , Personal(..)++    -- * Local key account+    , PrivateKeyAccount+    , PrivateKey(..)++    -- * Transaction paramitrization function and lenses+    , withParam+    , to+    , value+    , gasLimit+    , gasPrice+    , block+    , account++    ) where++import           Network.Ethereum.Account.Class      (Account (..))+import           Network.Ethereum.Account.Default    (DefaultAccount)+import           Network.Ethereum.Account.Internal   (account, block, gasLimit,+                                                      gasPrice, to, value,+                                                      withParam)+import           Network.Ethereum.Account.Personal   (Personal (..),+                                                      PersonalAccount)+import           Network.Ethereum.Account.PrivateKey (PrivateKey (..),+                                                      PrivateKeyAccount)
+ src/Network/Ethereum/Account/Class.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses  #-}++-- |+-- Module      :  Network.Ethereum.Account.Class+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Ethereum external owned account abstraction.+--++module Network.Ethereum.Account.Class where++import           Control.Monad.Trans              (MonadTrans)++import           Data.Solidity.Abi                (AbiGet)+import           Network.Ethereum.Api.Types       (TxReceipt)+import           Network.Ethereum.Contract.Method (Method)+import           Network.JsonRpc.TinyClient       (JsonRpc)++-- | Account is needed for sending transactions to blockchain+--+-- Typically account is provided by node. In this case node manage accounts:+-- encrypt and decrypt private keys, manipulate files etc. In other case web3+-- can derive account from private key and send to node already signed transactions.+--+class MonadTrans t => Account a t | t -> a where++    -- | Run computation with given account credentials+    withAccount :: JsonRpc m+                => a+                -- ^ Account params (like a password or private key)+                -> t m b+                -- ^ Computation that use account for sending transactions+                -> m b+                -- ^ Json-rpc monad++    -- | Send transaction to contract, like a 'write' command+    send :: (JsonRpc m, Method args)+         => args+         -- ^ Contract method arguments+         -> t m TxReceipt+         -- ^ Receipt of sended transaction++    -- | Call constant method of contract, like a 'read' command+    call :: (JsonRpc m, Method args, AbiGet result)+         => args+         -- ^ Contact method arguments+         -> t m result+         -- ^ Decoded result of method call+
+ src/Network/Ethereum/Account/Default.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards       #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeSynonymInstances  #-}++-- |+-- Module      :  Network.Ethereum.Account.Default+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Default node managed account (typically the first of accounts list).+--++module Network.Ethereum.Account.Default where++import           Control.Monad.Catch               (throwM)+import           Control.Monad.State.Strict        (get, runStateT)+import           Control.Monad.Trans               (MonadTrans (..))+import qualified Data.ByteArray                    as BA (convert)+import           Data.Maybe                        (listToMaybe)+import           Data.Monoid                       ((<>))+import           Data.Proxy                        (Proxy (..))++import           Data.Solidity.Abi.Codec           (decode, encode)+import           Network.Ethereum.Account.Class    (Account (..))+import           Network.Ethereum.Account.Internal (AccountT (..),+                                                    CallParam (..),+                                                    defaultCallParam, getCall,+                                                    getReceipt)+import qualified Network.Ethereum.Api.Eth          as Eth (accounts, call,+                                                           estimateGas,+                                                           sendTransaction)+import           Network.Ethereum.Api.Provider     (Web3Error (ParserFail))+import           Network.Ethereum.Api.Types        (Call (callData, callFrom, callGas))+import           Network.Ethereum.Contract.Method  (Method (..))++type DefaultAccount = AccountT ()++instance Account () DefaultAccount where+    withAccount _ =+        fmap fst . flip runStateT (defaultCallParam ()) . runAccountT++    send (args :: a) = do+        c <- getCall+        lift $ do+            accounts <- Eth.accounts+            let dat = selector (Proxy :: Proxy a) <> encode args+                params = c { callData = Just $ BA.convert dat+                           , callFrom = listToMaybe accounts }++            gasLimit <- Eth.estimateGas params+            let params' = params { callGas = Just gasLimit }++            getReceipt =<< Eth.sendTransaction params'++    call (args :: a) = do+        c <- getCall+        CallParam{..} <- get+        res <- lift $ do+            accounts <- Eth.accounts+            let dat    = selector (Proxy :: Proxy a) <> encode args+                params = c { callData = Just $ BA.convert dat+                           , callFrom = listToMaybe accounts }+            Eth.call params _block+        case decode res of+            Right r -> return r+            Left e  -> lift $ throwM (ParserFail e)
+ src/Network/Ethereum/Account/Internal.hs view
@@ -0,0 +1,130 @@+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE RecordWildCards            #-}++-- |+-- Module      :  Network.Ethereum.Account.Internal+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Internal types and functions of 'Account' module.+--++module Network.Ethereum.Account.Internal where++import           Control.Concurrent             (threadDelay)+import           Control.Monad.IO.Class         (liftIO)+import           Control.Monad.State.Strict     (MonadState (..), StateT (..),+                                                 withStateT)+import           Control.Monad.Trans            (MonadTrans (..))+import           Data.Default                   (Default (..))+import           Data.Maybe                     (fromMaybe)+import           Lens.Micro                     (Lens', lens)++import           Data.ByteArray.HexString       (HexString)+import           Data.Solidity.Prim             (Address)+import           Network.Ethereum.Account.Class (Account)+import qualified Network.Ethereum.Api.Eth       as Eth (getTransactionReceipt)+import           Network.Ethereum.Api.Types     (Call (..),+                                                 DefaultBlock (Latest),+                                                 TxReceipt (receiptTransactionHash))+import           Network.Ethereum.Unit          (Unit (..))+import           Network.JsonRpc.TinyClient     (JsonRpc)++-- | Account is needed to send transactions to blockchain++-- | Transaction parametrization data type+data CallParam p = CallParam+    { _to       :: Maybe Address+    -- ^ Transaction recepient+    , _value    :: Integer+    -- ^ Transaction value+    , _gasLimit :: Maybe Integer+    -- ^ Transaction gas limit+    , _gasPrice :: Maybe Integer+    -- ^ Transaction gas price+    , _block    :: DefaultBlock+    -- ^ Call block number+    , _account  :: p+    -- ^ Account params to sign transaction+    } deriving Eq++-- | Transaction recipient lens+to :: Lens' (CallParam p) Address+to = lens (fromMaybe def . _to) $ \a b -> a { _to = Just b }++-- | Transaction value lens+value :: Unit value => Lens' (CallParam p) value+value = lens (fromWei . _value) $ \a b -> a { _value = toWei b }++-- | Transaction gas limit lens+gasLimit :: Lens' (CallParam p) (Maybe Integer)+gasLimit = lens _gasLimit $ \a b -> a { _gasLimit = b }++-- | Transaction gas price lens+gasPrice :: Unit gasprice => Lens' (CallParam p) (Maybe gasprice)+gasPrice = lens (fmap fromWei . _gasPrice) $ \a b -> a { _gasPrice = toWei <$> b }++-- | Call execution block lens+block :: Lens' (CallParam p) DefaultBlock+block = lens _block $ \a b -> a { _block = b }++-- | EOA params lens+account :: Lens' (CallParam p) p+account = lens _account $ \a b -> a { _account = b }++-- | Monad transformer for sending parametrized transactions from account+newtype AccountT p m a = AccountT+    { runAccountT :: StateT (CallParam p) m a }+  deriving (Functor, Applicative, Monad, MonadTrans)++instance Monad m => MonadState (CallParam p) (AccountT p m) where+    get = AccountT get+    put = AccountT . put++-- | @withParam@ is very similar to @withStateT@ function, it's used+-- to set parameters of transaction locally and revert params after out of scope.+--+--  @+--  withAccount () $+--    withParam (to .~ tokenAddress) $+--      transfer alice 42+--  @+withParam :: Account p (AccountT p)+          => (CallParam p -> CallParam p)+          -> AccountT p m a+          -> AccountT p m a+{-# INLINE withParam #-}+withParam f m = AccountT $ withStateT f $ runAccountT m++defaultCallParam :: a -> CallParam a+{-# INLINE defaultCallParam #-}+defaultCallParam = CallParam def 0 Nothing Nothing Latest++getCall :: MonadState (CallParam p) m => m Call+getCall = do+    CallParam{..} <- get+    return $ def { callTo       = _to+                 , callValue    = Just $ fromInteger _value+                 , callGas      = fromInteger <$> _gasLimit+                 , callGasPrice = fromInteger <$> _gasPrice+                 }++getReceipt :: JsonRpc m => HexString -> m TxReceipt+getReceipt tx = do+    mbreceipt <- Eth.getTransactionReceipt tx+    case mbreceipt of+        Just receipt -> return receipt+        Nothing -> do+            liftIO $ threadDelay 100000+            -- TODO: avoid inifinite loop+            getReceipt tx++updateReceipt :: JsonRpc m => TxReceipt -> m TxReceipt+{-# INLINE updateReceipt #-}+updateReceipt = getReceipt . receiptTransactionHash
+ src/Network/Ethereum/Account/Personal.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE RecordWildCards       #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeSynonymInstances  #-}++-- |+-- Module      :  Network.Ethereum.Account.Personal+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Node managed unlockable account. Typically to send transaction from this account+-- password is required.+--++module Network.Ethereum.Account.Personal where++import           Control.Monad.State.Strict        (get, runStateT)+import           Control.Monad.Trans               (lift)+import qualified Data.ByteArray                    as BA (convert)+import           Data.Default                      (Default (..))+import           Data.Monoid                       ((<>))+import           Data.Proxy                        (Proxy (..))++import           Data.Solidity.Abi.Codec           (decode, encode)+import           Data.Solidity.Prim.Address        (Address)+import           Network.Ethereum.Account.Class    (Account (..))+import           Network.Ethereum.Account.Internal (AccountT (..),+                                                    CallParam (..),+                                                    defaultCallParam, getCall,+                                                    getReceipt)+import qualified Network.Ethereum.Api.Eth          as Eth (call, estimateGas)+import           Network.Ethereum.Api.Personal     (Passphrase)+import qualified Network.Ethereum.Api.Personal     as Personal (sendTransaction)+import           Network.Ethereum.Api.Types        (Call (callData, callFrom, callGas))+import           Network.Ethereum.Contract.Method  (selector)++-- | Unlockable node managed account params+data Personal = Personal {+    personalAddress    :: !Address+  , personalPassphrase :: !Passphrase+  } deriving (Eq, Show)++instance Default Personal where+    def = Personal def ""++type PersonalAccount = AccountT Personal++instance Account Personal PersonalAccount where+    withAccount a =+        fmap fst . flip runStateT (defaultCallParam a) . runAccountT++    send (args :: a) = do+        CallParam{..} <- get+        c <- getCall+        lift $ do+            let dat    = selector (Proxy :: Proxy a) <> encode args+                params = c { callFrom = Just $ personalAddress _account+                           , callData = Just $ BA.convert dat }++            gasLimit <- Eth.estimateGas params+            let params' = params { callGas = Just gasLimit }++            getReceipt =<< Personal.sendTransaction params' (personalPassphrase _account)++    call (args :: a) = do+        s <- get+        case s of+            CallParam _ _ _ _ block (Personal address _) -> do+                c <- getCall+                let dat = selector (Proxy :: Proxy a) <> encode args+                    params = c { callFrom = Just address, callData = Just $ BA.convert dat }+                res <- lift $ Eth.call params block+                case decode res of+                    Right r -> return r+                    Left e  -> fail e
+ src/Network/Ethereum/Account/PrivateKey.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE RecordWildCards       #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeSynonymInstances  #-}++-- |+-- Module      :  Network.Ethereum.Account.PrivateKey+-- Copyright   :  Alexander Krupenkin 2018+--                Roy Blankman 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--++module Network.Ethereum.Account.PrivateKey where++import           Control.Monad.State.Strict        (get, runStateT)+import           Control.Monad.Trans               (lift)+import           Crypto.Secp256k1                  (CompactRecSig (..), SecKey,+                                                    derivePubKey)+import           Data.ByteArray                    (convert)+import           Data.ByteString                   (ByteString)+import           Data.ByteString.Short             (fromShort)+import           Data.Default                      (Default (..))+import           Data.Maybe                        (fromJust, fromMaybe)+import           Data.Monoid                       (mempty, (<>))+import           Data.Proxy                        (Proxy (..))+import           Data.RLP                          (packRLP, rlpEncode)++import           Crypto.Ethereum                   (ecsign)+import           Data.ByteArray.HexString          (HexString, toBytes)+import           Data.Solidity.Abi.Codec           (decode, encode)+import           Data.Solidity.Prim.Address        (fromPubKey, toHexString)+import           Network.Ethereum.Account.Class    (Account (..))+import           Network.Ethereum.Account.Internal (AccountT (..),+                                                    CallParam (..),+                                                    defaultCallParam, getCall,+                                                    getReceipt)+import qualified Network.Ethereum.Api.Eth          as Eth (call, estimateGas,+                                                           getTransactionCount,+                                                           sendRawTransaction)+import           Network.Ethereum.Api.Types        (Call (..), unQuantity)+import           Network.Ethereum.Chain            (foundation)+import           Network.Ethereum.Contract.Method  (selector)+import           Network.Ethereum.Unit             (Shannon, toWei)++-- | Local EOA params+data PrivateKey = PrivateKey+    { privateKey      :: !SecKey+    , privateKeyChain :: !Integer+    } deriving (Eq, Show)++instance Default PrivateKey where+    def = PrivateKey "" foundation++type PrivateKeyAccount = AccountT PrivateKey++instance Account PrivateKey PrivateKeyAccount where+    withAccount a =+        fmap fst . flip runStateT (defaultCallParam a) . runAccountT++    send (args :: a) = do+        CallParam{..} <- get+        c <- getCall++        let dat     = selector (Proxy :: Proxy a) <> encode args+            address = fromPubKey (derivePubKey $ privateKey _account)++        nonce <- lift $ Eth.getTransactionCount address _block+        let params = c { callFrom  = Just address+                       , callNonce = Just nonce+                       , callData  = Just $ convert dat }++        gasLimit <- lift $ Eth.estimateGas params+        let params' = params { callGas = Just gasLimit }++        let signed = signTransaction params' (privateKeyChain _account) (privateKey _account)+        lift $ getReceipt =<< Eth.sendRawTransaction signed++    call (args :: a) = do+        CallParam{..} <- get+        c <- getCall+        let dat = selector (Proxy :: Proxy a) <> encode args+            address = fromPubKey (derivePubKey $ privateKey _account)+            params = c { callFrom = Just address, callData = Just $ convert dat }++        res <- lift $ Eth.call params _block+        case decode res of+            Right r -> return r+            Left e  -> fail e++encodeTransaction :: Call+                  -> Either Integer (Integer, ByteString, ByteString)+                  -> HexString+encodeTransaction Call{..} vrs = do+    let (to       :: ByteString) = maybe mempty (toBytes . toHexString) callTo+        (value    :: Integer)    = unQuantity $ fromJust callValue+        (nonce    :: Integer)    = unQuantity $ fromJust callNonce+        (gasPrice :: Integer)    = maybe defaultGasPrice unQuantity callGasPrice+        (gasLimit :: Integer)    = unQuantity $ fromJust callGas+        (input    :: ByteString) = convert $ fromMaybe mempty callData++    rlp $ case vrs of+        -- Unsigned transaction by EIP155+        Left chain_id   -> (nonce, gasPrice, gasLimit, to, value, input, chain_id, mempty, mempty)+        -- Signed transaction+        Right (v, r, s) -> (nonce, gasPrice, gasLimit, to, value, input, v, s, r)+  where+    rlp = convert . packRLP . rlpEncode+    defaultGasPrice = toWei (5 :: Shannon)++signTransaction :: Call+                -> Integer+                -> SecKey+                -> HexString+signTransaction c i key = encodeTransaction c $ Right (v', r, s)+  where+    unsigned = encodeTransaction c (Left i)+    recSig = ecsign key unsigned+    v  = fromIntegral $ getCompactRecSigV recSig+    r  = fromShort $ getCompactRecSigR recSig+    s  = fromShort $ getCompactRecSigS recSig+    v' = v + 35 + 2 * i  -- Improved 'v' according to EIP155
+ src/Network/Ethereum/Account/Safe.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE FlexibleContexts #-}++-- |+-- Module      :  Network.Ethereum.Account.Safe+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Safe sending of Ethereum transaction.+--++module Network.Ethereum.Account.Safe where++import           Control.Concurrent                (threadDelay)+import           Control.Monad.IO.Class            (liftIO)+import           Control.Monad.Trans               (lift)++import           Network.Ethereum.Account.Class    (Account (send))+import           Network.Ethereum.Account.Internal (updateReceipt)+import qualified Network.Ethereum.Api.Eth          as Eth+import           Network.Ethereum.Api.Types        (TxReceipt (receiptBlockNumber))+import           Network.Ethereum.Contract.Method  (Method)+import           Network.JsonRpc.TinyClient        (JsonRpc)++-- | Safe version of 'send' function of 'Account' typeclass+-- Waiting for some blocks of transaction confirmation before return+safeSend :: (Account p t, JsonRpc m, Method args, Monad (t m))+         => Integer+         -- ^ Confirmation in blocks+         -> args+         -- ^ Contract method arguments+         -> t m TxReceipt+         -- ^ Receipt of sended transaction+safeSend b a = lift . waiting =<< send a+  where+    waiting receipt =+        case receiptBlockNumber receipt of+            Nothing -> do+                liftIO $ threadDelay 1000000+                waiting =<< updateReceipt receipt+            Just bn -> do+                current <- Eth.blockNumber+                if current - bn >= fromInteger b+                    then return receipt+                    else do liftIO $ threadDelay 1000000+                            waiting receipt++-- | Count block confirmation to keep secure+-- According to Vitalik post+-- https://blog.ethereum.org/2015/09/14/on-slow-and-fast-block-times/+safeConfirmations :: Integer+safeConfirmations = 10
+ src/Network/Ethereum/Api/Eth.hs view
@@ -0,0 +1,248 @@+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module      :  Network.Ethereum.Web3.Eth+-- Copyright   :  Alexander Krupenkin 2016-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unknown+--+-- Ethereum node JSON-RPC API methods with `eth_` prefix.+--++module Network.Ethereum.Api.Eth where++import           Data.ByteArray.HexString   (HexString)+import           Data.Solidity.Prim.Address (Address)+import           Data.Text                  (Text)+import           Network.Ethereum.Api.Types (Block, Call, Change, DefaultBlock,+                                             Filter, Quantity, SyncingState,+                                             Transaction, TxReceipt)+import           Network.JsonRpc.TinyClient (JsonRpc (..))++-- | Returns the current ethereum protocol version.+protocolVersion :: JsonRpc m => m Text+{-# INLINE protocolVersion #-}+protocolVersion = remote "eth_protocolVersion"++-- | Returns an object with data about the sync status or false.+syncing :: JsonRpc m => m SyncingState+{-# INLINE syncing #-}+syncing = remote "eth_syncing"++-- | Returns the client coinbase address.+coinbase :: JsonRpc m => m Address+{-# INLINE coinbase #-}+coinbase = remote "eth_coinbase"++-- | Returns true if client is actively mining new blocks.+mining :: JsonRpc m => m Bool+{-# INLINE mining #-}+mining = remote "eth_mining"++-- | Returns the number of hashes per second that the node is mining with.+hashrate :: JsonRpc m => m Quantity+{-# INLINE hashrate #-}+hashrate = remote "eth_hashrate"++-- | Returns the value from a storage position at a given address.+getStorageAt :: JsonRpc m => Address -> Quantity -> DefaultBlock -> m HexString+{-# INLINE getStorageAt #-}+getStorageAt = remote "eth_getStorageAt"++-- | Returns the number of transactions sent from an address.+getTransactionCount :: JsonRpc m => Address -> DefaultBlock -> m Quantity+{-# INLINE getTransactionCount #-}+getTransactionCount = remote "eth_getTransactionCount"++-- | Returns the number of transactions in a block from a block matching the given block hash.+getBlockTransactionCountByHash :: JsonRpc m => HexString -> m Quantity+{-# INLINE getBlockTransactionCountByHash #-}+getBlockTransactionCountByHash = remote "eth_getBlockTransactionCountByHash"++-- | Returns the number of transactions in a block matching the+-- given block number.+getBlockTransactionCountByNumber :: JsonRpc m => Quantity -> m Quantity+{-# INLINE getBlockTransactionCountByNumber #-}+getBlockTransactionCountByNumber = remote "eth_getBlockTransactionCountByNumber"++-- | Returns the number of uncles in a block from a block matching the given+-- block hash.+getUncleCountByBlockHash :: JsonRpc m => HexString -> m Quantity+{-# INLINE getUncleCountByBlockHash #-}+getUncleCountByBlockHash = remote "eth_getUncleCountByBlockHash"++-- | Returns the number of uncles in a block from a block matching the given+-- block number.+getUncleCountByBlockNumber :: JsonRpc m => Quantity -> m Quantity+{-# INLINE getUncleCountByBlockNumber #-}+getUncleCountByBlockNumber = remote "eth_getUncleCountByBlockNumber"++-- | Returns code at a given address.+getCode :: JsonRpc m => Address -> DefaultBlock -> m HexString+{-# INLINE getCode #-}+getCode = remote "eth_getCode"++-- | Returns an Ethereum specific signature with:+-- sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).+sign :: JsonRpc m => Address -> HexString -> m HexString+{-# INLINE sign #-}+sign = remote "eth_sign"++-- | Creates new message call transaction or a contract creation,+-- if the data field contains code.+sendTransaction :: JsonRpc m => Call -> m HexString+{-# INLINE sendTransaction #-}+sendTransaction = remote "eth_sendTransaction"++-- | Creates new message call transaction or a contract creation for signed+-- transactions.+sendRawTransaction :: JsonRpc m => HexString -> m HexString+{-# INLINE sendRawTransaction #-}+sendRawTransaction = remote "eth_sendRawTransaction"++-- | Returns the balance of the account of given address.+getBalance :: JsonRpc m => Address -> DefaultBlock -> m Quantity+{-# INLINE getBalance #-}+getBalance = remote "eth_getBalance"++-- | Creates a filter object, based on filter options, to notify when the+-- state changes (logs). To check if the state has changed, call+-- 'getFilterChanges'.+newFilter :: JsonRpc m => Filter e -> m Quantity+{-# INLINE newFilter #-}+newFilter = remote "eth_newFilter"++-- | Polling method for a filter, which returns an array of logs which+-- occurred since last poll.+getFilterChanges :: JsonRpc m => Quantity -> m [Change]+{-# INLINE getFilterChanges #-}+getFilterChanges = remote "eth_getFilterChanges"++-- | Uninstalls a filter with given id.+-- Should always be called when watch is no longer needed.+uninstallFilter :: JsonRpc m => Quantity -> m Bool+{-# INLINE uninstallFilter #-}+uninstallFilter = remote "eth_uninstallFilter"++-- | Returns an array of all logs matching a given filter object.+getLogs :: JsonRpc m => Filter e -> m [Change]+{-# INLINE getLogs #-}+getLogs = remote "eth_getLogs"++-- | Executes a new message call immediately without creating a+-- transaction on the block chain.+call :: JsonRpc m => Call -> DefaultBlock -> m HexString+{-# INLINE call #-}+call = remote "eth_call"++-- | Makes a call or transaction, which won't be added to the blockchain and+-- returns the used gas, which can be used for estimating the used gas.+estimateGas :: JsonRpc m => Call -> m Quantity+{-# INLINE estimateGas #-}+estimateGas = remote "eth_estimateGas"++-- | Returns information about a block by hash.+getBlockByHash :: JsonRpc m => HexString -> m Block+{-# INLINE getBlockByHash #-}+getBlockByHash = flip (remote "eth_getBlockByHash") True++-- | Returns information about a block by block number.+getBlockByNumber :: JsonRpc m => Quantity -> m Block+{-# INLINE getBlockByNumber #-}+getBlockByNumber = flip (remote "eth_getBlockByNumber") True++-- | Returns the information about a transaction requested by transaction hash.+getTransactionByHash :: JsonRpc m => HexString -> m (Maybe Transaction)+{-# INLINE getTransactionByHash #-}+getTransactionByHash = remote "eth_getTransactionByHash"++-- | Returns information about a transaction by block hash and transaction index position.+getTransactionByBlockHashAndIndex :: JsonRpc m => HexString -> Quantity -> m (Maybe Transaction)+{-# INLINE getTransactionByBlockHashAndIndex #-}+getTransactionByBlockHashAndIndex = remote "eth_getTransactionByBlockHashAndIndex"++-- | Returns information about a transaction by block number and transaction+-- index position.+getTransactionByBlockNumberAndIndex :: JsonRpc m => DefaultBlock -> Quantity -> m (Maybe Transaction)+{-# INLINE getTransactionByBlockNumberAndIndex #-}+getTransactionByBlockNumberAndIndex = remote "eth_getTransactionByBlockNumberAndIndex"++-- | Returns the receipt of a transaction by transaction hash.+getTransactionReceipt :: JsonRpc m => HexString -> m (Maybe TxReceipt)+{-# INLINE getTransactionReceipt #-}+getTransactionReceipt = remote "eth_getTransactionReceipt"++-- | Returns a list of addresses owned by client.+accounts :: JsonRpc m => m [Address]+{-# INLINE accounts #-}+accounts = remote "eth_accounts"++-- | Creates a filter in the node, to notify when a new block arrives.+newBlockFilter :: JsonRpc m => m Quantity+{-# INLINE newBlockFilter #-}+newBlockFilter = remote "eth_newBlockFilter"++-- | Polling method for a block filter, which returns an array of block hashes+-- occurred since last poll.+getBlockFilterChanges :: JsonRpc m => Quantity -> m [HexString]+{-# INLINE getBlockFilterChanges #-}+getBlockFilterChanges = remote "eth_getFilterChanges"++-- | Returns the number of most recent block.+blockNumber :: JsonRpc m => m Quantity+{-# INLINE blockNumber #-}+blockNumber = remote "eth_blockNumber"++-- | Returns the current price per gas in wei.+gasPrice :: JsonRpc m => m Quantity+{-# INLINE gasPrice #-}+gasPrice = remote "eth_gasPrice"++-- | Returns information about a uncle of a block by hash and uncle index+-- position.+getUncleByBlockHashAndIndex :: JsonRpc m => HexString -> Quantity -> m Block+{-# INLINE getUncleByBlockHashAndIndex #-}+getUncleByBlockHashAndIndex = remote "eth_getUncleByBlockHashAndIndex"++-- | Returns information about a uncle of a block by number and uncle index+-- position.+getUncleByBlockNumberAndIndex :: JsonRpc m => DefaultBlock -> Quantity -> m Block+{-# INLINE getUncleByBlockNumberAndIndex #-}+getUncleByBlockNumberAndIndex = remote "eth_getUncleByBlockNumberAndIndex"++-- | Creates a filter in the node, to notify when new pending transactions arrive. To check if the state has changed, call getFilterChanges. Returns a FilterId.+newPendingTransactionFilter :: JsonRpc m => m Quantity+{-# INLINE newPendingTransactionFilter #-}+newPendingTransactionFilter = remote "eth_newPendingTransactionFilter"++-- | Returns an array of all logs matching filter with given id.+getFilterLogs :: JsonRpc m => Quantity -> m [Change]+{-# INLINE getFilterLogs #-}+getFilterLogs = remote "eth_getFilterLogs"++-- | Returns the hash of the current block, the seedHash, and the boundary+-- condition to be met ("target").+getWork :: JsonRpc m => m [HexString]+{-# INLINE getWork #-}+getWork = remote "eth_getWork"++-- | Used for submitting a proof-of-work solution.+-- Parameters:+-- 1. DATA, 8 Bytes - The nonce found (64 bits)+-- 2. DATA, 32 Bytes - The header's pow-hash (256 bits)+-- 3. DATA, 32 Bytes - The mix digest (256 bits)+submitWork :: JsonRpc m => HexString -> HexString -> HexString -> m Bool+{-# INLINE submitWork #-}+submitWork = remote "eth_submitWork"++-- | Used for submitting mining hashrate.+-- Parameters:+-- 1. Hashrate, a hexadecimal string representation (32 bytes) of the hash rate+-- 2. ID, String - A random hexadecimal(32 bytes) ID identifying the client+submitHashrate :: JsonRpc m => HexString -> HexString -> m Bool+{-# INLINE submitHashrate #-}+submitHashrate = remote "eth_submitHashrate"
+ src/Network/Ethereum/Api/Net.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module      :  Network.Ethereum.Api.Net+-- Copyright   :  Alexander Krupenkin 2016-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unknown+--+-- Ethereum node JSON-RPC API methods with `net_` prefix.+--++module Network.Ethereum.Api.Net where++import           Data.Text                  (Text)+import           Network.Ethereum.Api.Types (Quantity)+import           Network.JsonRpc.TinyClient (JsonRpc (..))++-- | Returns the current network id.+version :: JsonRpc m => m Text+{-# INLINE version #-}+version = remote "net_version"++-- | Returns true if client is actively listening for network connections.+listening :: JsonRpc m => m Bool+{-# INLINE listening #-}+listening = remote "net_listening"++-- | Returns number of peers currently connected to the client.+peerCount :: JsonRpc m => m Quantity+{-# INLINE peerCount #-}+peerCount = remote "net_peerCount"
+ src/Network/Ethereum/Api/Personal.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module      :  Network.Ethereum.Api.Personal+-- Copyright   :  Keagan McClelland 2018+-- License     :  BSD3+--+-- Maintainer  :  keagan.mcclelland@gmail.com+-- Stability   :  experimental+-- Portability :  unknown+--+-- Ethereum node JSON-RPC API methods with `personal_` prefix.+--++module Network.Ethereum.Api.Personal where++import           Data.ByteArray.HexString   (HexString)+import           Data.Solidity.Prim.Address (Address)+import           Data.Text                  (Text)+import           Network.Ethereum.Api.Types (Call)+import           Network.JsonRpc.TinyClient (JsonRpc (..))++type Passphrase = Text++-- | Imports the given unencrypted private key (hex string) into the key store, encrypting it with the passphrase.+--+-- Parameters:+--+-- 1. unencrypted private key+--+-- 2. passphrase+--+-- Returns: address of new account+importRawKey :: JsonRpc m => HexString -> Passphrase -> m Address+{-# INLINE importRawKey #-}+importRawKey = remote "personal_importRawKey"++-- | Returns all the Ethereum account addresses of all keys in the key store.+listAccounts :: JsonRpc m => m [Address]+{-# INLINE listAccounts #-}+listAccounts = remote "personal_listAccounts"++-- | Removes the private key with given address from memory. The account can no longer be used to send transactions.+lockAccount :: JsonRpc m => Address -> m Bool+{-# INLINE lockAccount #-}+lockAccount = remote "personal_lockAccount"++-- | Generates a new private key and stores it in the key store directory. The key file is encrypted with the given+-- passphrase. Returns the address of the new account.+newAccount :: JsonRpc m => Passphrase -> m Address+{-# INLINE newAccount #-}+newAccount = remote "personal_newAccount"++-- | Decrypts the key with the given address from the key store.+--+-- The unencrypted key will be held in memory until it is locked again+--+-- The account can be used with eth_sign and eth_sendTransaction while it is unlocked.+unlockAccount :: JsonRpc m => Address -> Passphrase -> m Bool+{-# INLINE unlockAccount #-}+unlockAccount = remote "personal_unlockAccount"++-- | Validate the given passphrase and submit transaction.+--+-- The transaction is the same argument as for eth_sendTransaction and contains the from address. If the passphrase can+-- be used to decrypt the private key belonging to the transaction 'callFrom', the transaction is verified, signed and+-- send onto the network. The account is not unlocked globally in the node and cannot be used in other RPC calls.+sendTransaction :: JsonRpc m => Call -> Passphrase -> m HexString+{-# INLINE sendTransaction #-}+sendTransaction = remote "personal_sendTransaction"++-- | Returns an Ethereum specific signature with:+--+-- sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).+--+-- when given a passphrase to decrypt the account's private key+sign :: JsonRpc m => HexString -> Address -> Passphrase -> m HexString+{-# INLINE sign #-}+sign = remote "personal_sign"++-- | Recovers address given message and signature data+--+-- Parameters:+--+-- 1. message: DATA, n bytes+--+-- 2. signature: DATA, 65 bytes+--+-- Returns: Address+ecRecover :: JsonRpc m => HexString -> HexString -> m Address+{-# INLINE ecRecover #-}+ecRecover = remote "personal_ecRecover"
+ src/Network/Ethereum/Api/Provider.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}++-- |+-- Module      :  Network.Ethereum.Api.Provider+-- Copyright   :  Alexander Krupenkin 2016-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  portable+--+-- Web3 service provider.+--++module Network.Ethereum.Api.Provider where++import           Control.Concurrent.Async   (Async, async)+import           Control.Exception          (Exception, try)+import           Control.Monad.Catch        (MonadThrow)+import           Control.Monad.IO.Class     (MonadIO (..))+import           Control.Monad.State        (MonadState (..))+import           Control.Monad.Trans.State  (StateT, evalStateT)+import           Data.Default               (Default (..))+import           GHC.Generics               (Generic)+import           Lens.Micro.Mtl             ((.=))+import           Network.HTTP.Client        (Manager)++import           Network.JsonRpc.TinyClient (JsonRpc, JsonRpcClient,+                                             defaultSettings, jsonRpcManager)++-- | Any communication with Ethereum node wrapped with 'Web3' monad+newtype Web3 a = Web3 { unWeb3 :: StateT JsonRpcClient IO a }+    deriving (Functor, Applicative, Monad, MonadIO, MonadThrow, MonadState JsonRpcClient)++instance JsonRpc Web3++-- | Some peace of error response+data Web3Error+  = JsonRpcFail !String+  -- ^ JSON-RPC communication error+  | ParserFail  !String+  -- ^ Error in parser state+  | UserFail    !String+  -- ^ Common head for user errors+  deriving (Show, Eq, Generic)++instance Exception Web3Error++--TODO: Change to `HttpProvider ServerUri | IpcProvider FilePath` to support IPC+-- | Web3 Provider+data Provider = HttpProvider String+  deriving (Show, Eq, Generic)++instance Default Provider where+  def = HttpProvider "http://localhost:8545"++-- | 'Web3' monad runner, using the supplied Manager+runWeb3With :: MonadIO m+            => Manager+            -> Provider+            -> Web3 a+            -> m (Either Web3Error a)+runWeb3With manager provider f =+    runWeb3' provider $ jsonRpcManager .= manager >> f++-- | 'Web3' monad runner+runWeb3' :: MonadIO m+         => Provider+         -> Web3 a+         -> m (Either Web3Error a)+runWeb3' (HttpProvider uri) f = do+    cfg <- defaultSettings uri+    liftIO . try . flip evalStateT cfg . unWeb3 $ f++-- | 'Web3' runner for default provider+runWeb3 :: MonadIO m+        => Web3 a+        -> m (Either Web3Error a)+{-# INLINE runWeb3 #-}+runWeb3 = runWeb3' def++-- | Fork 'Web3' with the same 'Provider' and 'Manager'+forkWeb3 :: Web3 a -> Web3 (Async a)+forkWeb3 f = liftIO . async . evalStateT (unWeb3 f) =<< get
+ src/Network/Ethereum/Api/Types.hs view
@@ -0,0 +1,298 @@+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE TemplateHaskell            #-}++-- |+-- Module      :  Network.Ethereum.Api.Types+-- Copyright   :  Alexander Krupenkin 2016-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  portable+--+-- Ethereum generic JSON-RPC types.+--++module Network.Ethereum.Api.Types where++import           Data.Aeson                 (FromJSON (..), Options (fieldLabelModifier, omitNothingFields),+                                             ToJSON (..), Value (Bool, String),+                                             defaultOptions, object, (.=))+import           Data.Aeson.TH              (deriveJSON)+import           Data.Default               (Default (..))+import           Data.Monoid                ((<>))+import           Data.Solidity.Prim.Address (Address)+import           Data.String                (IsString (..))+import qualified Data.Text                  as T (pack)+import qualified Data.Text.Lazy.Builder     as B (toLazyText)+import qualified Data.Text.Lazy.Builder.Int as B (hexadecimal)+import qualified Data.Text.Read             as R (decimal, hexadecimal)+import           GHC.Generics               (Generic)++import           Data.ByteArray.HexString   (HexString)+import           Data.String.Extra          (toLowerFirst)++-- | Should be viewed as type to representing QUANTITY in Web3 JSON RPC docs+--+--  When encoding QUANTITIES (integers, numbers): encode as hex, prefix with "0x",+--  the most compact representation (slight exception: zero should be represented as "0x0").+--  Examples:+--+--  0x41 (65 in decimal)+--  0x400 (1024 in decimal)+--  WRONG: 0x (should always have at least one digit - zero is "0x0")+--  WRONG: 0x0400 (no leading zeroes allowed)+--  WRONG: ff (must be prefixed 0x)+newtype Quantity = Quantity { unQuantity :: Integer }+    deriving (Num, Real, Integral, Enum, Eq, Ord, Generic)++instance Show Quantity where+    show = show . unQuantity++instance IsString Quantity where+    fromString ('0' : 'x' : hex) =+        case R.hexadecimal (T.pack hex) of+            Right (x, "") -> Quantity x+            _             -> error ("Quantity " ++ show hex ++ " is not valid hex")+    fromString num =+        case R.decimal (T.pack num) of+            Right (x, "") -> Quantity x+            _             -> error ("Quantity " ++ show num ++ " is not valid decimal")++instance ToJSON Quantity where+    toJSON (Quantity x) =+        let hexValue = B.toLazyText (B.hexadecimal x)+        in  toJSON ("0x" <> hexValue)++instance FromJSON Quantity where+    parseJSON (String v) =+        case R.hexadecimal v of+            Right (x, "") -> return (Quantity x)+            _             -> fail $ "Quantity " ++ show v <> " is not valid hex"+    parseJSON _ = fail "Quantity should be a JSON String"++-- | An object with sync status data.+data SyncActive = SyncActive+  { syncStartingBlock :: !Quantity+  -- ^ QUANTITY - The block at which the import started (will only be reset, after the sync reached his head).+  , syncCurrentBlock  :: !Quantity+  -- ^ QUANTITY - The current block, same as eth_blockNumber.+  , syncHighestBlock  :: !Quantity+  -- ^ QUANTITY - The estimated highest block.+  } deriving (Eq, Generic, Show)++$(deriveJSON (defaultOptions+    { fieldLabelModifier = toLowerFirst . drop 4 }) ''SyncActive)++-- | Sync state pulled by low-level call 'eth_syncing'.+data SyncingState = Syncing SyncActive | NotSyncing+    deriving (Eq, Generic, Show)++instance FromJSON SyncingState where+    parseJSON (Bool _) = pure NotSyncing+    parseJSON v        = Syncing <$> parseJSON v++-- | Changes pulled by low-level call 'eth_getFilterChanges', 'eth_getLogs',+-- and 'eth_getFilterLogs'+data Change = Change+  { changeLogIndex         :: !(Maybe Quantity)+  -- ^ QUANTITY - integer of the log index position in the block. null when its pending log.+  , changeTransactionIndex :: !(Maybe Quantity)+  -- ^ QUANTITY - integer of the transactions index position log was created from. null when its pending log.+  , changeTransactionHash  :: !(Maybe HexString)+  -- ^ DATA, 32 Bytes - hash of the transactions this log was created from. null when its pending log.+  , changeBlockHash        :: !(Maybe HexString)+  -- ^ DATA, 32 Bytes - hash of the block where this log was in. null when its pending. null when its pending log.+  , changeBlockNumber      :: !(Maybe Quantity)+  -- ^ QUANTITY - the block number where this log was in. null when its pending. null when its pending log.+  , changeAddress          :: !Address+  -- ^ DATA, 20 Bytes - address from which this log originated.+  , changeData             :: !HexString+  -- ^ DATA - contains one or more 32 Bytes non-indexed arguments of the log.+  , changeTopics           :: ![HexString]+  -- ^ Array of DATA - Array of 0 to 4 32 Bytes DATA of indexed log arguments.+  -- (In solidity: The first topic is the hash of the signature of the event+  -- (e.g. Deposit(address, bytes32, uint256)), except you declared the event with+  -- the anonymous specifier.)+  } deriving (Eq, Show, Generic)++$(deriveJSON (defaultOptions+    { fieldLabelModifier = toLowerFirst . drop 6 }) ''Change)++-- | The contract call params.+data Call = Call+  { callFrom     :: !(Maybe Address)+  -- ^ DATA, 20 Bytes - The address the transaction is send from.+  , callTo       :: !(Maybe Address)+  -- ^ DATA, 20 Bytes - (optional when creating new contract) The address the transaction is directed to.+  , callGas      :: !(Maybe Quantity)+  -- ^ QUANTITY - (optional, default: 3000000) Integer of the gas provided for the transaction execution. It will return unused gas.+  , callGasPrice :: !(Maybe Quantity)+  -- ^ QUANTITY - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas.+  , callValue    :: !(Maybe Quantity)+  -- ^ QUANTITY - (optional) Integer of the value sent with this transaction.+  , callData     :: !(Maybe HexString)+  -- ^ DATA - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters.+  , callNonce    :: !(Maybe Quantity)+  -- ^ QUANTITY - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.+  } deriving (Eq, Show, Generic)++$(deriveJSON (defaultOptions+    { fieldLabelModifier = toLowerFirst . drop 4+    , omitNothingFields = True }) ''Call)++instance Default Call where+    def = Call Nothing Nothing (Just 3000000) Nothing (Just 0) Nothing Nothing++-- | The state of blockchain for contract call.+data DefaultBlock = BlockWithNumber Quantity+                  | Earliest+                  | Latest+                  | Pending+    deriving (Eq, Show, Generic)++instance ToJSON DefaultBlock where+    toJSON (BlockWithNumber bn) = toJSON bn+    toJSON parameter            = toJSON . toLowerFirst . show $ parameter++-- | Low-level event filter data structure.+data Filter e = Filter+  { filterAddress   :: !(Maybe [Address])+  -- ^ DATA|Array, 20 Bytes - (optional) Contract address or a list of addresses from which logs should originate.+  , filterFromBlock :: !DefaultBlock+  -- ^ QUANTITY|TAG - (optional, default: "latest") Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions.+  , filterToBlock   :: !DefaultBlock+  -- ^ QUANTITY|TAG - (optional, default: "latest") Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions.+  , filterTopics    :: !(Maybe [Maybe HexString])+  -- ^ Array of DATA, - (optional) Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with "or" options.+  -- Topics are order-dependent. A transaction with a log with topics [A, B] will be matched by the following topic filters:+  -- * [] "anything"+  -- * [A] "A in first position (and anything after)"+  -- * [null, B] "anything in first position AND B in second position (and anything after)"+  -- * [A, B] "A in first position AND B in second position (and anything after)"+  -- * [[A, B], [A, B]] "(A OR B) in first position AND (A OR B) in second position (and anything after)"+  } deriving (Eq, Show, Generic)++instance ToJSON (Filter e) where+    toJSON f = object [ "address"   .= filterAddress f+                      , "fromBlock" .= filterFromBlock f+                      , "toBlock"   .= filterToBlock f+                      , "topics"    .= filterTopics f ]++instance Ord DefaultBlock where+    compare Pending Pending                         = EQ+    compare Latest Latest                           = EQ+    compare Earliest Earliest                       = EQ+    compare (BlockWithNumber a) (BlockWithNumber b) = compare a b+    compare _ Pending                               = LT+    compare Pending Latest                          = GT+    compare _ Latest                                = LT+    compare Earliest _                              = LT+    compare a b                                     = case compare b a of+                                                        LT -> GT+                                                        GT -> LT+                                                        EQ -> EQ++-- | The Receipt of a Transaction+data TxReceipt = TxReceipt+  { receiptTransactionHash   :: !HexString+  -- ^ DATA, 32 Bytes - hash of the transaction.+  , receiptTransactionIndex  :: !Quantity+  -- ^ QUANTITY - index of the transaction.+  , receiptBlockHash         :: !(Maybe HexString)+  -- ^ DATA, 32 Bytes - hash of the block where this transaction was in. null when its pending.+  , receiptBlockNumber       :: !(Maybe Quantity)+  -- ^ QUANTITY - block number where this transaction was in. null when its pending.+  , receiptCumulativeGasUsed :: !Quantity+  -- ^ QUANTITY - The total amount of gas used when this transaction was executed in the block.+  , receiptGasUsed           :: !Quantity+  -- ^ QUANTITY - The amount of gas used by this specific transaction alone.+  , receiptContractAddress   :: !(Maybe Address)+  -- ^ DATA, 20 Bytes - The contract address created, if the transaction was a contract creation, otherwise null.+  , receiptLogs              :: ![Change]+  -- ^ Array - Array of log objects, which this transaction generated.+  , receiptLogsBloom         :: !HexString+  -- ^ DATA, 256 Bytes - Bloom filter for light clients to quickly retrieve related logs.+  , receiptStatus            :: !(Maybe Quantity)+  -- ^ QUANTITY either 1 (success) or 0 (failure)+  } deriving (Show, Generic)++$(deriveJSON (defaultOptions+    { fieldLabelModifier = toLowerFirst . drop 7 }) ''TxReceipt)++-- | Transaction information.+data Transaction = Transaction+  { txHash             :: !HexString+  -- ^ DATA, 32 Bytes - hash of the transaction.+  , txNonce            :: !Quantity+  -- ^ QUANTITY - the number of transactions made by the sender prior to this one.+  , txBlockHash        :: !(Maybe HexString)+  -- ^ DATA, 32 Bytes - hash of the block where this transaction was in. null when its pending.+  , txBlockNumber      :: !(Maybe Quantity)+  -- ^ QUANTITY - block number where this transaction was in. null when its pending.+  , txTransactionIndex :: !(Maybe Quantity)+  -- ^ QUANTITY - integer of the transactions index position in the block. null when its pending.+  , txFrom             :: !Address+  -- ^ DATA, 20 Bytes - address of the sender.+  , txTo               :: !(Maybe Address)+  -- ^ DATA, 20 Bytes - address of the receiver. null when its a contract creation transaction.+  , txValue            :: !Quantity+  -- ^ QUANTITY - value transferred in Wei.+  , txGasPrice         :: !Quantity+  -- ^ QUANTITY - gas price provided by the sender in Wei.+  , txGas              :: !Quantity+  -- ^ QUANTITY - gas provided by the sender.+  , txInput            :: !HexString+  -- ^ DATA - the data send along with the transaction.+  } deriving (Eq, Show, Generic)++$(deriveJSON (defaultOptions+    { fieldLabelModifier = toLowerFirst . drop 2 }) ''Transaction)++-- | Block information.+data Block = Block+  { blockNumber           :: !(Maybe Quantity)+  -- ^ QUANTITY - the block number. null when its pending block.+  , blockHash             :: !(Maybe HexString)+  -- ^ DATA, 32 Bytes - hash of the block. null when its pending block.+  , blockParentHash       :: !HexString+  -- ^ DATA, 32 Bytes - hash of the parent block.+  , blockNonce            :: !(Maybe HexString)+  -- ^ DATA, 8 Bytes - hash of the generated proof-of-work. null when its pending block.+  , blockSha3Uncles       :: !HexString+  -- ^ DATA, 32 Bytes - SHA3 of the uncles data in the block.+  , blockLogsBloom        :: !(Maybe HexString)+  -- ^ DATA, 256 Bytes - the bloom filter for the logs of the block. null when its pending block.+  , blockTransactionsRoot :: !HexString+  -- ^ DATA, 32 Bytes - the root of the transaction trie of the block.+  , blockStateRoot        :: !HexString+  -- ^ DATA, 32 Bytes - the root of the final state trie of the block.+  , blockReceiptRoot      :: !(Maybe HexString)+  -- ^ DATA, 32 Bytes - the root of the receipts trie of the block.+  , blockMiner            :: !Address+  -- ^ DATA, 20 Bytes - the address of the beneficiary to whom the mining rewards were given.+  , blockDifficulty       :: !Quantity+  -- ^ QUANTITY - integer of the difficulty for this block.+  , blockTotalDifficulty  :: !Quantity+  -- ^ QUANTITY - integer of the total difficulty of the chain until this block.+  , blockExtraData        :: !HexString+  -- ^ DATA - the "extra data" field of this block.+  , blockSize             :: !Quantity+  -- ^ QUANTITY - integer the size of this block in bytes.+  , blockGasLimit         :: !Quantity+  -- ^ QUANTITY - the maximum gas allowed in this block.+  , blockGasUsed          :: !Quantity+  -- ^ QUANTITY - the total used gas by all transactions in this block.+  , blockTimestamp        :: !Quantity+  -- ^ QUANTITY - the unix timestamp for when the block was collated.+  , blockTransactions     :: ![Transaction]+  -- ^ Array of transaction objects.+  , blockUncles           :: ![HexString]+  -- ^ Array - Array of uncle hashes.+  } deriving (Show, Generic)++$(deriveJSON (defaultOptions+    { fieldLabelModifier = toLowerFirst . drop 5 }) ''Block)
+ src/Network/Ethereum/Api/Web3.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module      :  Network.Ethereum.Api.Web3+-- Copyright   :  Alexander Krupenkin 2016-2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unknown+--+-- Ethereum node JSON-RPC API methods with `web3_` prefix.+--++module Network.Ethereum.Api.Web3 where++import           Data.ByteArray.HexString   (HexString)+import           Data.Text                  (Text)+import           Network.JsonRpc.TinyClient (JsonRpc (..))++-- | Returns current node version string.+clientVersion :: JsonRpc m => m Text+{-# INLINE clientVersion #-}+clientVersion = remote "web3_clientVersion"++-- | Returns Keccak-256 (not the standardized SHA3-256) of the given data.+sha3 :: JsonRpc m => HexString -> m HexString+{-# INLINE sha3 #-}+sha3 = remote "web3_sha3"
+ src/Network/Ethereum/Chain.hs view
@@ -0,0 +1,36 @@+-- |+-- Module      :  Network.Ethereum.Chain+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+--++module Network.Ethereum.Chain where++-- | Ethereum mainnet CHAIN_ID from EIP155+foundation :: Integer+foundation = 1++-- | Ethereum testnet CHAIN_ID from EIP155+ropsten :: Integer+ropsten = 3++-- | Rokenby CHAIN_ID from EIP155+rikenby :: Integer+rikenby = 4++-- | Kovan CHAIN_ID from EIP155+kovan :: Integer+kovan = 42++-- | Ethereum Classic mainnet CHAIN_ID from EIP155+classic :: Integer+classic = 61++-- | Ethereum Classic testnet CHAIN_ID from EIP155+classicTestnet :: Integer+classicTestnet = 62
+ src/Network/Ethereum/Contract.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeSynonymInstances  #-}++-- |+-- Module      :  Network.Ethereum.Contract+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Smart contract type class and utils. A contract in the sense of Solidity+-- is a collection of code (its functions) and data (its state) that resides+-- at a specific address on the Ethereum blockchain.+--++module Network.Ethereum.Contract where++import           Data.Proxy                       (Proxy)+import           Data.Text                        (Text)++import           Data.ByteArray.HexString         (HexString)+import           Data.Solidity.Prim.Address       (Address)+import           Network.Ethereum.Account.Class   (Account)+import           Network.Ethereum.Account.Safe    (safeConfirmations, safeSend)+import           Network.Ethereum.Api.Types       (receiptContractAddress)+import           Network.Ethereum.Contract.Method (Method)+import           Network.JsonRpc.TinyClient       (JsonRpc)++-- | Contract description type clase+class Contract a where+    -- | Contract Solidity ABI+    -- https://solidity.readthedocs.io/en/latest/abi-spec.html+    abi :: Proxy a -> Text++    -- | Contract bytecode as hex string+    bytecode :: Proxy a -> HexString++-- | Create new smart contract on blockchain+new :: (Account p t, JsonRpc m, Method a, Monad (t m))+    => a+    -- ^ Contract constructor+    -> t m (Maybe Address)+    -- ^ Address of deployed contract when transaction success+new = fmap receiptContractAddress . safeSend safeConfirmations
src/Network/Ethereum/Contract/Event.hs view
@@ -1,11 +1,6 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RecordWildCards       #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeFamilies          #-}- -- | -- Module      :  Network.Ethereum.Contract.Event--- Copyright   :  Alexander Krupenkin 2016-2018+-- Copyright   :  Alexander Krupenkin 2016 -- License     :  BSD3 -- -- Maintainer  :  mail@akru.me@@ -15,183 +10,13 @@ -- Ethereum contract event support. -- -module Network.Ethereum.Contract.Event (-    EventAction(..)-  , event-  , event'-  , eventMany'-  ) where--import           Control.Concurrent             (threadDelay)-import           Control.Monad                  (forM, void, when)-import           Control.Monad.IO.Class         (liftIO)-import           Control.Monad.Trans.Class      (lift)-import           Control.Monad.Trans.Reader     (ReaderT (..))-import           Data.Either                    (rights)-import           Data.Machine                   (MachineT, asParts, autoM,-                                                 await, construct, final,-                                                 mapping, repeatedly, runT,-                                                 unfoldPlan, (~>))-import           Data.Machine.Plan              (PlanT, stop, yield)-import           Data.Maybe                     (catMaybes, listToMaybe)--import           Control.Concurrent.Async       (Async)-import           Network.Ethereum.ABI.Event     (DecodeEvent (..))-import qualified Network.Ethereum.Web3.Eth      as Eth-import           Network.Ethereum.Web3.Provider (Web3, forkWeb3)-import           Network.Ethereum.Web3.Types    (Change (..), DefaultBlock (..),-                                                 Filter (..), Quantity)---- | Event callback control response-data EventAction = ContinueEvent-                 -- ^ Continue to listen events-                 | TerminateEvent-                 -- ^ Terminate event listener-  deriving (Show, Eq)---- | Run 'event\'' one block at a time.-event :: DecodeEvent i ni e-      => Filter e-      -> (e -> ReaderT Change Web3 EventAction)-      -> Web3 (Async ())-event fltr = forkWeb3 . event' fltr---- | Same as 'event', but does not immediately spawn a new thread.-event' :: DecodeEvent i ni e-       => Filter e-       -> (e -> ReaderT Change Web3 EventAction)-       -> Web3 ()-event' fltr = eventMany' fltr 0---- | 'eventMany\'' take s a filter, a window size, and a handler.------ It runs the handler over the results of 'eventLogs' results using--- 'reduceEventStream'. If no 'TerminateEvent' action is thrown and--- the toBlock is not yet reached, it then transitions to polling.----eventMany' :: DecodeEvent i ni e-           => Filter e-           -> Integer-           -> (e -> ReaderT Change Web3 EventAction)-           -> Web3 ()-eventMany' fltr window handler = do-    start <- mkBlockNumber $ filterFromBlock fltr-    let initState = FilterStreamState { fssCurrentBlock = start-                                      , fssInitialFilter = fltr-                                      , fssWindowSize = window-                                      }-    mLastProcessedFilterState <- reduceEventStream (playLogs initState) handler-    case mLastProcessedFilterState of-      Nothing -> startPolling fltr {filterFromBlock = BlockWithNumber start}-      Just (act, lastBlock) -> do-        end <- mkBlockNumber . filterToBlock $ fltr-        when (act /= TerminateEvent && lastBlock < end) $-          let pollingFromBlock = lastBlock + 1-          in startPolling fltr {filterFromBlock = BlockWithNumber pollingFromBlock}-  where-    startPolling fltr' = do-      filterId <- Eth.newFilter fltr'-      let pollTo = filterToBlock fltr'-      void $ reduceEventStream (pollFilter filterId pollTo) handler---- | Effectively a mapM_ over the machine using the given handler.-reduceEventStream :: Monad m-                  => MachineT m k [FilterChange a]-                  -> (a -> ReaderT Change m EventAction)-                  -> m (Maybe (EventAction, Quantity))-reduceEventStream filterChanges handler = fmap listToMaybe . runT $-       filterChanges-    ~> autoM (processChanges handler)-    ~> asParts-    ~> runWhile (\(act, _) -> act /= TerminateEvent)-    ~> final-  where-    runWhile p = repeatedly $ do-      v <- await-      if p v-        then yield v-        else yield v >> stop-    processChanges :: Monad m-                   => (a -> ReaderT Change m EventAction)-                   -> [FilterChange a]-                   -> m [(EventAction, Quantity)]-    processChanges handler' changes = fmap catMaybes $-        forM changes $ \FilterChange{..} -> do-            act <- flip runReaderT filterChangeRawChange $-                handler' filterChangeEvent-            return ((,) act <$> changeBlockNumber filterChangeRawChange)--data FilterChange a = FilterChange { filterChangeRawChange :: Change-                                   , filterChangeEvent     :: a-                                   }---- | 'playLogs' streams the 'filterStream' and calls eth_getLogs on these 'Filter' objects.-playLogs :: DecodeEvent i ni e-         => FilterStreamState e-         -> MachineT Web3 k [FilterChange e]-playLogs s = filterStream s-          ~> autoM Eth.getLogs-          ~> mapping mkFilterChanges---- | Polls a filter from the given filterId until the target toBlock is reached.-pollFilter :: forall i ni e k . DecodeEvent i ni e-           => Quantity-           -> DefaultBlock-           -> MachineT Web3 k [FilterChange e]-pollFilter i = construct . pollPlan i-  where-    pollPlan :: Quantity -> DefaultBlock -> PlanT k [FilterChange e] Web3 ()-    pollPlan fid end = do-      bn <- lift $ Eth.blockNumber-      if BlockWithNumber bn > end-        then do-          _ <- lift $ Eth.uninstallFilter fid-          stop-        else do-          liftIO $ threadDelay 1000000-          changes <- lift $ Eth.getFilterChanges fid-          yield $ mkFilterChanges changes-          pollPlan fid end--mkFilterChanges :: DecodeEvent i ni e-                => [Change]-                -> [FilterChange e]-mkFilterChanges = rights-                . fmap (\c@Change{..} -> FilterChange c <$> decodeEvent c)--data FilterStreamState e =-  FilterStreamState { fssCurrentBlock  :: Quantity-                    , fssInitialFilter :: Filter e-                    , fssWindowSize    :: Integer-                    }----- | 'filterStream' is a machine which represents taking an initial filter--- over a range of blocks b1, ... bn (where bn is possibly `Latest` or `Pending`,--- but b1 is an actual block number), and making a stream of filter objects--- which cover this filter in intervals of size `windowSize`. The machine--- halts whenever the `fromBlock` of a spanning filter either (1) excedes then--- initial filter's `toBlock` or (2) is greater than the chain head's block number.-filterStream :: FilterStreamState e-             -> MachineT Web3 k (Filter e)-filterStream initialPlan = unfoldPlan initialPlan filterPlan-  where-    filterPlan :: FilterStreamState e -> PlanT k (Filter e) Web3 (FilterStreamState e)-    filterPlan initialState@FilterStreamState{..} = do-      end <- lift . mkBlockNumber $ filterToBlock fssInitialFilter-      if fssCurrentBlock > end-        then stop-        else do-          let to' = min end $ fssCurrentBlock + fromInteger fssWindowSize-              filter' = fssInitialFilter { filterFromBlock = BlockWithNumber fssCurrentBlock-                                         , filterToBlock = BlockWithNumber to'-                                         }-          yield filter'-          filterPlan $ initialState { fssCurrentBlock = to' + 1 }+module Network.Ethereum.Contract.Event+    (+      module Network.Ethereum.Contract.Event.Common+    , module Network.Ethereum.Contract.Event.SingleFilter+    , module Network.Ethereum.Contract.Event.MultiFilter+    ) where --- | Coerce a 'DefaultBlock' into a numerical block number.-mkBlockNumber :: DefaultBlock -> Web3 Quantity-mkBlockNumber bm = case bm of-  BlockWithNumber bn -> return bn-  Earliest           -> return 0-  _                  -> Eth.blockNumber+import           Network.Ethereum.Contract.Event.Common+import           Network.Ethereum.Contract.Event.MultiFilter+import           Network.Ethereum.Contract.Event.SingleFilter
+ src/Network/Ethereum/Contract/Event/Common.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards       #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE UndecidableInstances  #-}++-- |+-- Module      :  Network.Ethereum.Contract.Event.Common+-- Copyright   :  FOAM team <http://foam.space> 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Common event manipulation functions.+--++module Network.Ethereum.Contract.Event.Common  where++import           Control.Concurrent            (threadDelay)+import           Control.Exception             (Exception, throwIO)+import           Control.Monad.IO.Class        (liftIO)+import           Data.Either                   (lefts, rights)++import           Data.Solidity.Event           (DecodeEvent (..))+import qualified Network.Ethereum.Api.Eth      as Eth+import           Network.Ethereum.Api.Provider (Web3)+import           Network.Ethereum.Api.Types    (Change (..), DefaultBlock (..),+                                                Filter (..), Quantity)++-- | Event callback control response+data EventAction = ContinueEvent+                 -- ^ Continue to listen events+                 | TerminateEvent+                 -- ^ Terminate event listener+  deriving (Show, Eq)+++data FilterChange a =+  FilterChange { filterChangeRawChange :: Change+               , filterChangeEvent     :: a+               }++data EventParseFailure = EventParseFailure String deriving (Show)++instance Exception EventParseFailure++mkFilterChanges :: DecodeEvent i ni e+                => [Change]+                -> IO [FilterChange e]+mkFilterChanges changes =+  let eChanges = map (\c@Change{..} -> FilterChange c <$> decodeEvent c) changes+      ls = lefts eChanges+      rs = rights eChanges+  in if ls /= [] then throwIO (EventParseFailure $ show ls) else pure rs+++data FilterStreamState e =+  FilterStreamState { fssCurrentBlock  :: Quantity+                    , fssInitialFilter :: Filter e+                    , fssWindowSize    :: Integer+                    }+++-- | Coerce a 'DefaultBlock' into a numerical block number.+mkBlockNumber :: DefaultBlock -> Web3 Quantity+mkBlockNumber bm = case bm of+  BlockWithNumber bn -> return bn+  Earliest           -> return 0+  _                  -> Eth.blockNumber+++pollTillBlockProgress+  :: Quantity+  -> Web3 Quantity+pollTillBlockProgress currentBlock = do+  bn <- Eth.blockNumber+  if currentBlock >= bn+    then do+      liftIO $ threadDelay 3000000+      pollTillBlockProgress currentBlock+       else pure bn
+ src/Network/Ethereum/Contract/Event/MultiFilter.hs view
@@ -0,0 +1,457 @@+{-# LANGUAGE DataKinds              #-}+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE GADTs                  #-}+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE RankNTypes             #-}+{-# LANGUAGE RecordWildCards        #-}+{-# LANGUAGE ScopedTypeVariables    #-}+{-# LANGUAGE TypeApplications       #-}+{-# LANGUAGE TypeFamilies           #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE TypeOperators          #-}+{-# LANGUAGE UndecidableInstances   #-}++-- |+-- Module      :  Network.Ethereum.Contract.Event.MultiFilter+-- Copyright   :  FOAM team <http://foam.space> 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Support for parallel multiple event filters.+--++module  Network.Ethereum.Contract.Event.MultiFilter+    (+    -- * The @MultiFilter@ type+      MultiFilter(..)+    , minStartBlock+    , minEndBlock+    , modifyMultiFilter++    -- * With geth filters+    , multiEvent+    , multiEvent'+    , multiEventMany'++    -- * Without geth filters+    , multiEventNoFilter+    , multiEventNoFilter'+    , multiEventManyNoFilter'++    -- * Re-exports+    , Handlers+    , Handler(..)+    , Rec(..)+    ) where++import           Control.Concurrent                     (threadDelay)+import           Control.Concurrent.Async               (Async)+import           Control.Monad                          (forM, void, when)+import           Control.Monad.IO.Class                 (MonadIO (..))+import           Control.Monad.Trans.Class              (lift)+import           Control.Monad.Trans.Reader             (ReaderT (..))+import           Data.List                              (sortOn)+import           Data.Machine                           (MachineT, asParts,+                                                         autoM, await,+                                                         construct, final,+                                                         repeatedly, runT,+                                                         unfoldPlan, (~>))+import           Data.Machine.Plan                      (PlanT, stop, yield)+import           Data.Maybe                             (catMaybes, fromJust,+                                                         listToMaybe)+import           Data.Monoid                            ((<>))+import           Data.Proxy                             (Proxy (..))+import           Data.Tagged                            (Tagged (..))+import           Data.Vinyl                             (Rec ((:&), RNil),+                                                         RecApplicative)+import           Data.Vinyl.CoRec                       (CoRec (..), Field,+                                                         FoldRec, Handler (H),+                                                         Handlers, coRecToRec,+                                                         firstField, match,+                                                         onField)+import           Data.Vinyl.Functor                     (Compose (..),+                                                         Identity (..))+import           Data.Vinyl.TypeLevel                   (AllAllSat)++import           Data.Solidity.Event                    (DecodeEvent (..))+import qualified Network.Ethereum.Api.Eth               as Eth+import           Network.Ethereum.Api.Provider          (Web3, forkWeb3)+import           Network.Ethereum.Api.Types             (Change (..),+                                                         DefaultBlock (..),+                                                         Filter (..), Quantity)+import           Network.Ethereum.Contract.Event.Common++--------------------------------------------------------------------------------+-- | MultiFilters+--------------------------------------------------------------------------------++data MultiFilter (es :: [*]) where+  NilFilters :: MultiFilter '[]+  (:?) :: Filter e -> MultiFilter es -> MultiFilter (e ': es)++infixr 5 :?++minEndBlock+  :: MultiFilter es+  -> DefaultBlock+minEndBlock NilFilters             = Pending+minEndBlock (Filter _ _ e _ :? fs) = e `min` minEndBlock fs++minStartBlock+  :: MultiFilter es+  -> DefaultBlock+minStartBlock NilFilters             = Pending+minStartBlock (Filter _ s _ _ :? fs) = s `min` minStartBlock fs++modifyMultiFilter+  :: (forall e. Filter e -> Filter e)+  -> MultiFilter es+  -> MultiFilter es+modifyMultiFilter _ NilFilters = NilFilters+modifyMultiFilter h (f :? fs)  = h f :? modifyMultiFilter h fs+++multiEvent+  :: ( PollFilters es+     , QueryAllLogs es+     , MapHandlers Web3 es (WithChange es)+     , AllAllSat '[HasLogIndex] (WithChange es)+     , RecApplicative (WithChange es)+     )+  => MultiFilter es+  -> Handlers es (ReaderT Change Web3 EventAction)+  -> Web3 (Async ())+multiEvent fltrs = forkWeb3 . multiEvent' fltrs++multiEvent'+  :: ( PollFilters es+     , QueryAllLogs es+     , MapHandlers Web3 es (WithChange es)+     , AllAllSat '[HasLogIndex] (WithChange es)+     , RecApplicative (WithChange es)+     )+  => MultiFilter es+  -> Handlers es (ReaderT Change Web3 EventAction)+  -> Web3 ()+multiEvent' fltrs = multiEventMany' fltrs 0++data MultiFilterStreamState es =+  MultiFilterStreamState { mfssCurrentBlock       :: Quantity+                         , mfssInitialMultiFilter :: MultiFilter es+                         , mfssWindowSize         :: Integer+                         }+++multiEventMany'+  :: ( PollFilters es+     , QueryAllLogs es+     , MapHandlers Web3 es (WithChange es)+     , AllAllSat '[HasLogIndex] (WithChange es)+     , RecApplicative (WithChange es)+     )+  => MultiFilter es+  -> Integer+  -> Handlers es (ReaderT Change Web3 EventAction)+  -> Web3 ()+multiEventMany' fltrs window handlers = do+    start <- mkBlockNumber $ minStartBlock fltrs+    let initState =+          MultiFilterStreamState { mfssCurrentBlock = start+                                 , mfssInitialMultiFilter = fltrs+                                 , mfssWindowSize = window+                                 }+    mLastProcessedFilterState <- reduceMultiEventStream (playMultiLogs initState) handlers+    case mLastProcessedFilterState of+      Nothing -> startPolling (modifyMultiFilter (\f -> f {filterFromBlock = BlockWithNumber start}) fltrs)+      Just (act, lastBlock) -> do+        end <- mkBlockNumber . minEndBlock $ fltrs+        when (act /= TerminateEvent && lastBlock < end) $+          let pollingFromBlock = lastBlock + 1+          in startPolling (modifyMultiFilter (\f -> f {filterFromBlock = BlockWithNumber pollingFromBlock}) fltrs)+  where+    startPolling fltrs' = do+      fIds <- openMultiFilter fltrs'+      let pollTo = minEndBlock fltrs'+      void $ reduceMultiEventStream (pollMultiFilter fIds pollTo) handlers++multiFilterStream+  :: MultiFilterStreamState es+  -> MachineT Web3 k (MultiFilter es)+multiFilterStream initialPlan = do+  unfoldPlan initialPlan $ \s -> do+    end <- lift . mkBlockNumber . minEndBlock . mfssInitialMultiFilter $ initialPlan+    filterPlan end s+  where+    filterPlan :: Quantity -> MultiFilterStreamState es -> PlanT k (MultiFilter es) Web3 (MultiFilterStreamState es)+    filterPlan end initialState@MultiFilterStreamState{..} = do+      if mfssCurrentBlock > end+        then stop+        else do+          let to' = min end $ mfssCurrentBlock + fromInteger mfssWindowSize+              h :: forall e. Filter e -> Filter e+              h f = f { filterFromBlock = BlockWithNumber mfssCurrentBlock+                      , filterToBlock = BlockWithNumber to'+                      }+          yield (modifyMultiFilter h mfssInitialMultiFilter)+          filterPlan end initialState { mfssCurrentBlock = to' + 1 }++weakenCoRec+  :: ( RecApplicative ts+     , FoldRec (t ': ts) (t ': ts)+     )+  => Field ts+  -> Field (t ': ts)+weakenCoRec = fromJust . firstField . (Compose Nothing :&) . coRecToRec++type family WithChange (es :: [*]) = (es' :: [*]) | es' -> es where+  WithChange '[] = '[]+  WithChange (e : es) = FilterChange e : WithChange es++class QueryAllLogs (es :: [*]) where+  queryAllLogs :: MultiFilter es -> Web3 [Field (WithChange es)]++instance QueryAllLogs '[] where+  queryAllLogs NilFilters = pure []++instance forall e i ni es.+  ( DecodeEvent i ni e+  , QueryAllLogs es+  , RecApplicative (WithChange es)+  , FoldRec (FilterChange e : WithChange es) (WithChange es)+  ) => QueryAllLogs (e:es) where++  queryAllLogs (f  :? fs) = do+    changes <- Eth.getLogs f+    filterChanges <- liftIO . mkFilterChanges @_ @_ @e $ changes+    filterChanges' <- queryAllLogs fs+    pure $ map (CoRec . Identity) filterChanges <> map weakenCoRec filterChanges'++class HasLogIndex a where+  getLogIndex :: a -> Maybe (Quantity, Quantity)++instance HasLogIndex (FilterChange e) where+  getLogIndex FilterChange{..} =+    (,) <$> changeBlockNumber filterChangeRawChange <*> changeLogIndex filterChangeRawChange++sortChanges+  :: ( AllAllSat '[HasLogIndex] es+     , RecApplicative es+     )+  => [Field es]+  -> [Field es]+sortChanges changes =+  let sorterProj change = onField (Proxy @'[HasLogIndex]) getLogIndex change+  in sortOn sorterProj changes++class MapHandlers m es es' where+  mapHandlers+    :: Handlers es (ReaderT Change m EventAction)+    -> Handlers es' (m (Maybe (EventAction, Quantity)))++instance Monad m => MapHandlers m '[] '[] where+  mapHandlers RNil = RNil++instance+  ( Monad m+  , MapHandlers m es es'+  ) => MapHandlers m (e : es) (FilterChange e : es') where++  mapHandlers (H f :& fs) =+    let f' FilterChange{..} = do+          act <- runReaderT (f filterChangeEvent) filterChangeRawChange+          return ((,) act <$> changeBlockNumber filterChangeRawChange)+    in H f' :& mapHandlers fs+++reduceMultiEventStream+  :: ( Monad m+     , MapHandlers m es (WithChange es)+     )+  => MachineT m k [Field (WithChange es)]+  -> Handlers es (ReaderT Change m EventAction)+  -> m (Maybe (EventAction, Quantity))+reduceMultiEventStream filterChanges handlers = fmap listToMaybe . runT $+       filterChanges+    ~> autoM (processChanges handlers)+    ~> asParts+    ~> runWhile (\(act, _) -> act /= TerminateEvent)+    ~> final+  where+    runWhile p = repeatedly $ do+      v <- await+      if p v+        then yield v+        else yield v >> stop+    processChanges handlers' changes = fmap catMaybes $+        forM changes $ \fc -> match fc (mapHandlers handlers')++-- | 'playLogs' streams the 'filterStream' and calls eth_getLogs on these 'Filter' objects.+playMultiLogs+  :: forall es k.+     ( QueryAllLogs es+     , AllAllSat '[HasLogIndex] (WithChange es)+     , RecApplicative (WithChange es)+     )+  => MultiFilterStreamState es+  -> MachineT Web3 k [Field (WithChange es)]+playMultiLogs s = fmap sortChanges $+     multiFilterStream s+  ~> autoM queryAllLogs++data TaggedFilterIds (es :: [*]) where+  TaggedFilterNil :: TaggedFilterIds '[]+  TaggedFilterCons :: Tagged e Quantity -> TaggedFilterIds es -> TaggedFilterIds (e : es)++class PollFilters (es :: [*]) where+  openMultiFilter :: MultiFilter es -> Web3 (TaggedFilterIds es)+  checkMultiFilter :: TaggedFilterIds es -> Web3 [Field (WithChange es)]+  closeMultiFilter :: TaggedFilterIds es -> Web3 ()++instance PollFilters '[] where+  openMultiFilter _ = pure TaggedFilterNil+  checkMultiFilter _ = pure []+  closeMultiFilter _ = pure ()++instance forall e i ni es.+  ( DecodeEvent i ni e+  , PollFilters es+  , RecApplicative (WithChange es)+  , FoldRec (FilterChange e : WithChange es) (WithChange es)+  ) => PollFilters (e:es) where+  openMultiFilter (f :? fs) = do+    fId <- Eth.newFilter f+    fsIds <- openMultiFilter fs+    pure $ TaggedFilterCons (Tagged fId) fsIds++  checkMultiFilter (TaggedFilterCons (Tagged fId) fsIds) = do+    changes <- Eth.getFilterChanges fId+    filterChanges <- liftIO . mkFilterChanges @_ @_ @e $ changes+    filterChanges' <- checkMultiFilter @es fsIds+    pure  $ map (CoRec . Identity) filterChanges <>  map weakenCoRec filterChanges'++  closeMultiFilter (TaggedFilterCons (Tagged fId) fsIds) = do+    _ <- Eth.uninstallFilter fId+    closeMultiFilter fsIds+++-- | Polls a filter from the given filterId until the target toBlock is reached.+pollMultiFilter+  :: ( PollFilters es+     , RecApplicative (WithChange es)+     , AllAllSat '[HasLogIndex] (WithChange es)+     )+  => TaggedFilterIds es+  -> DefaultBlock+  -> MachineT Web3 k [Field (WithChange es)]+pollMultiFilter is = construct . pollPlan is+  where+    -- pollPlan :: TaggedFilterIds es -> DefaultBlock -> PlanT k [Field (Map (TyCon1 FilterChange) es)] Web3 ()+    pollPlan (fIds :: TaggedFilterIds es) end = do+      bn <- lift $ Eth.blockNumber+      if BlockWithNumber bn > end+        then do+          _ <- lift $ closeMultiFilter fIds+          stop+        else do+          liftIO $ threadDelay 1000000+          changes <- lift $ sortChanges <$> checkMultiFilter fIds+          yield changes+          pollPlan fIds end++--------------------------------------------------------------------------------+++multiEventNoFilter+  :: ( QueryAllLogs es+     , MapHandlers Web3 es (WithChange es)+     , AllAllSat '[HasLogIndex] (WithChange es)+     , RecApplicative (WithChange es)+     )+  => MultiFilter es+  -> Handlers es (ReaderT Change Web3 EventAction)+  -> Web3 (Async ())+multiEventNoFilter fltrs = forkWeb3 . multiEventNoFilter' fltrs++multiEventNoFilter'+  :: ( QueryAllLogs es+     , MapHandlers Web3 es (WithChange es)+     , AllAllSat '[HasLogIndex] (WithChange es)+     , RecApplicative (WithChange es)+     )+  => MultiFilter es+  -> Handlers es (ReaderT Change Web3 EventAction)+  -> Web3 ()+multiEventNoFilter' fltrs = multiEventManyNoFilter' fltrs 0+++multiEventManyNoFilter'+  :: ( QueryAllLogs es+     , MapHandlers Web3 es (WithChange es)+     , AllAllSat '[HasLogIndex] (WithChange es)+     , RecApplicative (WithChange es)+     )+  => MultiFilter es+  -> Integer+  -> Handlers es (ReaderT Change Web3 EventAction)+  -> Web3 ()+multiEventManyNoFilter' fltrs window handlers = do+    start <- mkBlockNumber $ minStartBlock fltrs+    let initState =+          MultiFilterStreamState { mfssCurrentBlock = start+                                 , mfssInitialMultiFilter = fltrs+                                 , mfssWindowSize = window+                                 }+    mLastProcessedFilterState <- reduceMultiEventStream (playMultiLogs initState) handlers+    case mLastProcessedFilterState of+      Nothing ->+        let pollingFilterState =+              MultiFilterStreamState { mfssCurrentBlock = start+                                     , mfssInitialMultiFilter = fltrs+                                     , mfssWindowSize = 0+                                     }+        in void $ reduceMultiEventStream (playNewMultiLogs pollingFilterState) handlers+      Just (act, lastBlock) -> do+        end <- mkBlockNumber . minEndBlock $ fltrs+        when (act /= TerminateEvent && lastBlock < end) $+          let pollingFilterState = MultiFilterStreamState { mfssCurrentBlock = lastBlock + 1+                                                          , mfssInitialMultiFilter = fltrs+                                                          , mfssWindowSize = 0+                                                          }+          in void $ reduceMultiEventStream (playNewMultiLogs pollingFilterState) handlers++newMultiFilterStream+  :: MultiFilterStreamState es+  -> MachineT Web3 k (MultiFilter es)+newMultiFilterStream initialPlan = do+  unfoldPlan initialPlan $ \s -> do+    let end = minEndBlock . mfssInitialMultiFilter $ initialPlan+    filterPlan end s+  where+    filterPlan :: DefaultBlock -> MultiFilterStreamState es -> PlanT k (MultiFilter es) Web3 (MultiFilterStreamState es)+    filterPlan end initialState@MultiFilterStreamState{..} = do+      if BlockWithNumber mfssCurrentBlock > end+        then stop+        else do+          newestBlockNumber <- lift . pollTillBlockProgress $ mfssCurrentBlock+          let h :: forall e. Filter e -> Filter e+              h f = f { filterFromBlock = BlockWithNumber mfssCurrentBlock+                      , filterToBlock = BlockWithNumber newestBlockNumber+                      }+          yield (modifyMultiFilter h mfssInitialMultiFilter)+          filterPlan end initialState { mfssCurrentBlock = newestBlockNumber + 1 }++playNewMultiLogs+  :: forall es k.+     ( QueryAllLogs es+     , AllAllSat '[HasLogIndex] (WithChange es)+     , RecApplicative (WithChange es)+     )+  => MultiFilterStreamState es+  -> MachineT Web3 k [Field (WithChange es)]+playNewMultiLogs s = fmap sortChanges $+     newMultiFilterStream s+  ~> autoM queryAllLogs
+ src/Network/Ethereum/Contract/Event/SingleFilter.hs view
@@ -0,0 +1,256 @@+{-# LANGUAGE DataKinds              #-}+{-# LANGUAGE FlexibleContexts       #-}+{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE GADTs                  #-}+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE RankNTypes             #-}+{-# LANGUAGE RecordWildCards        #-}+{-# LANGUAGE ScopedTypeVariables    #-}+{-# LANGUAGE TypeFamilies           #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE TypeOperators          #-}+{-# LANGUAGE UndecidableInstances   #-}++-- |+-- Module      :  Network.Ethereum.Contract.Event.SingleFilter+-- Copyright   :  FOAM team <http://foam.space> 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Simple contract event filter support.+--++module Network.Ethereum.Contract.Event.SingleFilter+    (+      event+    , event'+    , eventMany'+    , eventNoFilter+    , eventNoFilter'+    , eventManyNoFilter'+    ) where++import           Control.Concurrent                     (threadDelay)+import           Control.Concurrent.Async               (Async)+import           Control.Monad                          (forM, void, when)+import           Control.Monad.IO.Class                 (MonadIO (..))+import           Control.Monad.Trans.Class              (lift)+import           Control.Monad.Trans.Reader             (ReaderT (..))+import           Data.Machine                           (MachineT, asParts,+                                                         autoM, await,+                                                         construct, final,+                                                         repeatedly, runT,+                                                         unfoldPlan, (~>))+import           Data.Machine.Plan                      (PlanT, stop, yield)+import           Data.Maybe                             (catMaybes, listToMaybe)++import           Data.Solidity.Event                    (DecodeEvent (..))+import qualified Network.Ethereum.Api.Eth               as Eth+import           Network.Ethereum.Api.Provider          (Web3, forkWeb3)+import           Network.Ethereum.Api.Types             (Change (..),+                                                         DefaultBlock (..),+                                                         Filter (..), Quantity)+import           Network.Ethereum.Contract.Event.Common++-- | Run 'event\'' one block at a time.+event :: DecodeEvent i ni e+      => Filter e+      -> (e -> ReaderT Change Web3 EventAction)+      -> Web3 (Async ())+event fltr = forkWeb3 . event' fltr++-- | Same as 'event', but does not immediately spawn a new thread.+event' :: DecodeEvent i ni e+       => Filter e+       -> (e -> ReaderT Change Web3 EventAction)+       -> Web3 ()+event' fltr = eventMany' fltr 0++-- | 'eventMany\'' take s a filter, a window size, and a handler.+--+-- It runs the handler over the results of 'eventLogs' results using+-- 'reduceEventStream'. If no 'TerminateEvent' action is thrown and+-- the toBlock is not yet reached, it then transitions to polling.+--+eventMany' :: DecodeEvent i ni e+           => Filter e+           -> Integer+           -> (e -> ReaderT Change Web3 EventAction)+           -> Web3 ()+eventMany' fltr window handler = do+    start <- mkBlockNumber $ filterFromBlock fltr+    let initState = FilterStreamState { fssCurrentBlock = start+                                      , fssInitialFilter = fltr+                                      , fssWindowSize = window+                                      }+    mLastProcessedFilterState <- reduceEventStream (playOldLogs initState) handler+    case mLastProcessedFilterState of+      Nothing -> startPolling fltr {filterFromBlock = BlockWithNumber start}+      Just (act, lastBlock) -> do+        end <- mkBlockNumber . filterToBlock $ fltr+        when (act /= TerminateEvent && lastBlock < end) $+          let pollingFromBlock = lastBlock + 1+          in startPolling fltr {filterFromBlock = BlockWithNumber pollingFromBlock}+  where+    startPolling fltr' = do+      filterId <- Eth.newFilter fltr'+      let pollTo = filterToBlock fltr'+      void $ reduceEventStream (pollFilter filterId pollTo) handler++-- | Effectively a mapM_ over the machine using the given handler.+reduceEventStream :: Monad m+                  => MachineT m k [FilterChange a]+                  -> (a -> ReaderT Change m EventAction)+                  -> m (Maybe (EventAction, Quantity))+reduceEventStream filterChanges handler = fmap listToMaybe . runT $+       filterChanges+    ~> autoM (processChanges handler)+    ~> asParts+    ~> runWhile (\(act, _) -> act /= TerminateEvent)+    ~> final+  where+    runWhile p = repeatedly $ do+      v <- await+      if p v+        then yield v+        else yield v >> stop+    processChanges :: Monad m+                   => (a -> ReaderT Change m EventAction)+                   -> [FilterChange a]+                   -> m [(EventAction, Quantity)]+    processChanges handler' changes = fmap catMaybes $+        forM changes $ \FilterChange{..} -> do+            act <- flip runReaderT filterChangeRawChange $+                handler' filterChangeEvent+            return ((,) act <$> changeBlockNumber filterChangeRawChange)++-- | 'playLogs' streams the 'filterStream' and calls eth_getLogs on these 'Filter' objects.+playOldLogs+  :: DecodeEvent i ni e+  => FilterStreamState e+  -> MachineT Web3 k [FilterChange e]+playOldLogs s = filterStream s+          ~> autoM Eth.getLogs+          ~> autoM (liftIO . mkFilterChanges)++-- | Polls a filter from the given filterId until the target toBlock is reached.+pollFilter :: forall i ni e k . DecodeEvent i ni e+           => Quantity+           -> DefaultBlock+           -> MachineT Web3 k [FilterChange e]+pollFilter i = construct . pollPlan i+  where+    pollPlan :: Quantity -> DefaultBlock -> PlanT k [FilterChange e] Web3 ()+    pollPlan fid end = do+      bn <- lift $ Eth.blockNumber+      if BlockWithNumber bn > end+        then do+          _ <- lift $ Eth.uninstallFilter fid+          stop+        else do+          liftIO $ threadDelay 1000000+          changes <- lift $ Eth.getFilterChanges fid >>= liftIO . mkFilterChanges+          yield $ changes+          pollPlan fid end+++-- | 'filterStream' is a machine which represents taking an initial filter+-- over a range of blocks b1, ... bn (where bn is possibly `Latest` or `Pending`,+-- but b1 is an actual block number), and making a stream of filter objects+-- which cover this filter in intervals of size `windowSize`. The machine+-- halts whenever the `fromBlock` of a spanning filter either (1) excedes then+-- initial filter's `toBlock` or (2) is greater than the chain head's block number.+filterStream :: FilterStreamState e+             -> MachineT Web3 k (Filter e)+filterStream initialPlan = unfoldPlan initialPlan filterPlan+  where+    filterPlan :: FilterStreamState e -> PlanT k (Filter e) Web3 (FilterStreamState e)+    filterPlan initialState@FilterStreamState{..} = do+      end <- lift . mkBlockNumber $ filterToBlock fssInitialFilter+      if fssCurrentBlock > end+        then stop+        else do+          let to' = min end $ fssCurrentBlock + fromInteger fssWindowSize+              filter' = fssInitialFilter { filterFromBlock = BlockWithNumber fssCurrentBlock+                                         , filterToBlock = BlockWithNumber to'+                                         }+          yield filter'+          filterPlan $ initialState { fssCurrentBlock = to' + 1 }++--------------------------------------------------------------------------------++-- | Run 'event\'' one block at a time.+eventNoFilter+  :: DecodeEvent i ni e+  => Filter e+  -> (e -> ReaderT Change Web3 EventAction)+  -> Web3 (Async ())+eventNoFilter fltr = forkWeb3 . event' fltr++-- | Same as 'event', but does not immediately spawn a new thread.+eventNoFilter'+  :: DecodeEvent i ni e+  => Filter e+  -> (e -> ReaderT Change Web3 EventAction)+  -> Web3 ()+eventNoFilter' fltr = eventManyNoFilter' fltr 0++eventManyNoFilter'+  :: DecodeEvent i ni e+  => Filter e+  -> Integer+  -> (e -> ReaderT Change Web3 EventAction)+  -> Web3 ()+eventManyNoFilter' fltr window handler = do+    start <- mkBlockNumber $ filterFromBlock fltr+    let initState = FilterStreamState { fssCurrentBlock = start+                                      , fssInitialFilter = fltr+                                      , fssWindowSize = window+                                      }+    mLastProcessedFilterState <- reduceEventStream (playOldLogs initState) handler+    case mLastProcessedFilterState of+      Nothing ->+        let pollingFilterState = FilterStreamState { fssCurrentBlock = start+                                                   , fssInitialFilter = fltr+                                                   , fssWindowSize = 1+                                                   }++        in void $ reduceEventStream (playNewLogs pollingFilterState) handler+      Just (act, lastBlock) -> do+        end <- mkBlockNumber . filterToBlock $ fltr+        when (act /= TerminateEvent && lastBlock < end) $+          let pollingFilterState = FilterStreamState { fssCurrentBlock = lastBlock + 1+                                                     , fssInitialFilter = fltr+                                                     , fssWindowSize = 1+                                                     }+          in void $ reduceEventStream (playNewLogs pollingFilterState) handler++-- | 'playLogs' streams the 'filterStream' and calls eth_getLogs on these 'Filter' objects.+playNewLogs+  :: DecodeEvent i ni e+  => FilterStreamState e+  -> MachineT Web3 k [FilterChange e]+playNewLogs s =+     newFilterStream s+  ~> autoM Eth.getLogs+  ~> autoM (liftIO . mkFilterChanges)++newFilterStream+  :: FilterStreamState e+  -> MachineT Web3 k (Filter e)+newFilterStream initialState = unfoldPlan initialState filterPlan+  where+    filterPlan :: FilterStreamState e -> PlanT k (Filter e) Web3 (FilterStreamState e)+    filterPlan s@FilterStreamState{..} = do+      if BlockWithNumber fssCurrentBlock > filterToBlock fssInitialFilter+        then stop+        else do+          newestBlockNumber <- lift . pollTillBlockProgress $ fssCurrentBlock+          let filter' = fssInitialFilter { filterFromBlock = BlockWithNumber fssCurrentBlock+                                         , filterToBlock = BlockWithNumber newestBlockNumber+                                         }+          yield filter'+          filterPlan $ s { fssCurrentBlock = newestBlockNumber + 1 }
src/Network/Ethereum/Contract/Method.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE ScopedTypeVariables #-}- -- | -- Module      :  Network.Ethereum.Contract.Method -- Copyright   :  Alexander Krupenkin 2016-2018@@ -12,60 +10,24 @@ -- Ethereum contract method support. -- -module Network.Ethereum.Contract.Method (-    Method(..)-  , call-  , sendTx-  ) where--import           Control.Monad.Catch             (throwM)-import           Data.Monoid                     ((<>))-import           Data.Proxy                      (Proxy (..))+module Network.Ethereum.Contract.Method where -import           Network.Ethereum.ABI.Class      (ABIGet, ABIPut, ABIType (..))-import           Network.Ethereum.ABI.Codec      (decode, encode)-import           Network.Ethereum.ABI.Prim.Bytes (Bytes)-import qualified Network.Ethereum.Web3.Eth       as Eth-import           Network.Ethereum.Web3.Provider  (Web3, Web3Error (ParserFail))-import           Network.Ethereum.Web3.Types     (Call (callData), DefaultBlock,-                                                  Hash)+import           Data.Proxy                (Proxy)+import           Data.Solidity.Abi         (AbiPut, AbiType (..))+import           Data.Solidity.Abi.Generic ()+import           Data.Solidity.Prim.Bytes  (Bytes) -class ABIPut a => Method a where-  selector :: Proxy a -> Bytes+-- | Smart contract method encoding+class AbiPut a => Method a where+    -- | Solidity function selector+    -- https://solidity.readthedocs.io/en/latest/abi-spec.html#function-selector-and-argument-encoding+    selector :: Proxy a -> Bytes -instance ABIType () where-  isDynamic _ = False+instance AbiType () where+    isDynamic _ = False -instance ABIPut ()+instance AbiPut () --- | Send transaction without method selection+-- | Fallback contract method instance Method () where-  selector = mempty---- | 'sendTx' is used to submit a state changing transaction.-sendTx :: Method a-       => Call-       -- ^ Call configuration-       -> a-       -- ^ method data-       -> Web3 Hash-sendTx call' (dat :: a) =-    let sel = selector (Proxy :: Proxy a)-    in Eth.sendTransaction (call' { callData = Just $ sel <> encode dat })---- | 'call' is used to call contract methods that have no state changing effects.-call :: (Method a, ABIGet b)-     => Call-     -- ^ Call configuration-     -> DefaultBlock-     -- ^ State mode for constant call (latest or pending)-     -> a-     -- ^ Method data-     -> Web3 b-     -- ^ 'Web3' wrapped result-call call' mode (dat :: a) = do-    let sel = selector (Proxy :: Proxy a)-    res <- Eth.call (call' { callData = Just $ sel <> encode dat }) mode-    case decode res of-        Left e  -> throwM $ ParserFail $ "Unable to parse response: " ++ e-        Right x -> return x+    selector _   = mempty
src/Network/Ethereum/Contract/TH.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes       #-} {-# LANGUAGE TemplateHaskell   #-}@@ -17,7 +18,7 @@ -- The Application Binary Interface is the standard way to interact -- with contracts in the Ethereum ecosystem. It can be described by -- specially JSON file, like @ERC20.json@. This module use TemplateHaskell--- for generation described in ABI contract methods and events. Helper+-- for generation described in Abi contract methods and events. Helper -- functions and instances inserted in haskell module and can be used in -- another modules or in place. --@@ -35,10 +36,18 @@ -- Full code example available in examples folder. -- -module Network.Ethereum.Contract.TH (abi, abiFrom) where+module Network.Ethereum.Contract.TH+    (+    -- * The contract quasiquoters+      abi+    , abiFrom+    ) where +import           Control.Applicative              ((<|>)) import           Control.Monad                    (replicateM, (<=<))-import           Data.Aeson                       (eitherDecode)+import qualified Data.Aeson                       as Aeson (encode)+import           Data.ByteArray                   (convert)+import qualified Data.Char                        as Char import           Data.Default                     (Default (..)) import           Data.List                        (group, sort, uncons) import           Data.Monoid                      ((<>))@@ -47,39 +56,43 @@ import qualified Data.Text                        as T import qualified Data.Text.Lazy                   as LT import qualified Data.Text.Lazy.Encoding          as LT+import           Data.Tuple.OneTuple              (only) import           Generics.SOP                     (Generic) import qualified GHC.Generics                     as GHC (Generic) import           Language.Haskell.TH import           Language.Haskell.TH.Quote+import           Lens.Micro                       ((^?))+import           Lens.Micro.Aeson                 (key, _JSON, _String) +import           Data.Solidity.Abi                (AbiGet, AbiPut, AbiType (..))+import           Data.Solidity.Event              (IndexedEvent (..))+import           Data.Solidity.Prim               (Address, Bytes, BytesN, IntN,+                                                   ListN, UIntN) import           Data.String.Extra                (toLowerFirst, toUpperFirst)-import           Network.Ethereum.ABI.Class       (ABIGet, ABIPut, ABIType (..))-import           Network.Ethereum.ABI.Event       (IndexedEvent (..))-import           Network.Ethereum.ABI.Json        (ContractABI (..),+import           Language.Solidity.Abi            (ContractAbi (..),                                                    Declaration (..),                                                    EventArg (..),                                                    FunctionArg (..),                                                    SolidityType (..), eventId,                                                    methodId, parseSolidityType)-import           Network.Ethereum.ABI.Prim        (Address, Bytes, BytesN, IntN,-                                                   ListN, Singleton (..), UIntN)-import           Network.Ethereum.Contract.Method (Method (..), call, sendTx)-import           Network.Ethereum.Web3.Provider   (Web3)-import           Network.Ethereum.Web3.Types      (Call, DefaultBlock (..),-                                                   Filter (..), Hash)+import           Network.Ethereum.Account.Class   (Account (..))+import           Network.Ethereum.Api.Types       (DefaultBlock (..),+                                                   Filter (..), TxReceipt)+import qualified Network.Ethereum.Contract        as Contract (Contract (..))+import           Network.Ethereum.Contract.Method (Method (..))+import           Network.JsonRpc.TinyClient       (JsonRpc) --- | Read contract ABI from file+-- | Read contract Abi from file abiFrom :: QuasiQuoter abiFrom = quoteFile abi --- | QQ reader for contract ABI+-- | QQ reader for contract Abi abi :: QuasiQuoter abi = QuasiQuoter-  { quoteDec  = quoteAbiDec-  , quoteExp  = quoteAbiExp-  , quotePat  = undefined-  , quoteType = undefined-  }+    { quoteDec  = quoteAbiDec+    , quoteExp  = quoteAbiExp+    , quotePat  = undefined+    , quoteType = undefined }  -- | Instance declaration with empty context instanceD' :: Name -> TypeQ -> [DecQ] -> DecQ@@ -88,14 +101,14 @@  -- | Simple data type declaration with one constructor dataD' :: Name -> ConQ -> [Name] -> DecQ-dataD' name rec derive =-    dataD (cxt []) name [] Nothing [rec] [derivClause Nothing (conT <$> derive)]+dataD' name rec' derive =+    dataD (cxt []) name [] Nothing [rec'] [derivClause Nothing (conT <$> derive)]  -- | Simple function declaration funD' :: Name -> [PatQ] -> ExpQ -> DecQ funD' name p f = funD name [clause p (normalB f) []] --- | ABI and Haskell types association+-- | Abi and Haskell types association toHSType :: SolidityType -> TypeQ toHSType s = case s of     SolidityBool        -> conT ''Bool@@ -112,9 +125,9 @@     expandVector :: [Int] -> SolidityType -> TypeQ     expandVector ns a = case uncons ns of       Just (n, rest) ->-        if length rest == 0-          then (conT ''ListN) `appT` numLit n `appT` toHSType a-          else (conT ''ListN) `appT` numLit n `appT` expandVector rest a+        if null rest+          then conT ''ListN `appT` numLit n `appT` toHSType a+          else conT ''ListN `appT` numLit n `appT` expandVector rest a       _ -> error $ "Impossible Nothing branch in `expandVector`: " ++ show ns ++ " " ++ show a  typeQ :: Text -> TypeQ@@ -139,44 +152,47 @@            -- ^ Results            -> DecsQ funWrapper c name dname args result = do-    a : _ : vars <- replicateM (length args + 2) (newName "t")-    let params = appsE $ conE dname : fmap varE vars+    vars <- replicateM (length args) (newName "t")+    a <- varT <$> newName "a"+    t <- varT <$> newName "t"+    m <- varT <$> newName "m" -    sequence $ if c-        then-          [ sigD name $ [t|$(arrowing $ [t|Call|] : inputT ++ [outputT])|]-          , funD' name (varP <$> a : vars) $-              case result of-                Just [_] -> [|unSingleton <$> call $(varE a) Latest $(params)|]-                _        -> [|call $(varE a) Latest $(params)|]-          ] -        else-          [ sigD name $ [t|$(arrowing $ [t|Call|] : inputT ++ [[t|Web3 Hash|]])|]-          , funD' name (varP <$> a : vars) $-                [|sendTx $(varE a) $(params)|] ]+    let params  = appsE $ conE dname : fmap varE vars+        inputT  = fmap (typeQ . funArgType) args+        outputT = case result of+            Nothing  -> [t|$t $m ()|]+            Just [x] -> [t|$t $m $(typeQ $ funArgType x)|]+            Just xs  -> let outs = fmap (typeQ . funArgType) xs+                         in  [t|$t $m $(foldl appT (tupleT (length xs)) outs)|]++    sequence [+        sigD name $ [t|+            (JsonRpc $m, Account $a $t, Functor ($t $m)) =>+                $(arrowing $ inputT ++ [if c then outputT else [t|$t $m TxReceipt|]])+            |]+      , if c+            then funD' name (varP <$> vars) $ case result of+                    Just [_] -> [|only <$> call $(params)|]+                    _        -> [|call $(params)|]+            else funD' name (varP <$> vars) $ [|send $(params)|]+      ]   where     arrowing []       = error "Impossible branch call"     arrowing [x]      = x     arrowing (x : xs) = [t|$x -> $(arrowing xs)|]-    inputT  = fmap (typeQ . funArgType) args-    outputT = case result of-        Nothing  -> [t|Web3 ()|]-        Just [x] -> [t|Web3 $(typeQ $ funArgType x)|]-        Just xs  -> let outs = fmap (typeQ . funArgType) xs-                    in  [t|Web3 $(foldl appT (tupleT (length xs)) outs)|]  mkDecl :: Declaration -> DecsQ -mkDecl ev@(DEvent name inputs anonymous) = sequence+mkDecl ev@(DEvent uncheckedName inputs anonymous) = sequence     [ dataD' indexedName (normalC indexedName (map (toBang <=< tag) indexedArgs)) derivingD     , instanceD' indexedName (conT ''Generic) []-    , instanceD' indexedName (conT ''ABIType) [funD' 'isDynamic [] [|const False|]]-    , instanceD' indexedName (conT ''ABIGet) []+    , instanceD' indexedName (conT ''AbiType) [funD' 'isDynamic [] [|const False|]]+    , instanceD' indexedName (conT ''AbiGet) []     , dataD' nonIndexedName (normalC nonIndexedName (map (toBang <=< tag) nonIndexedArgs)) derivingD     , instanceD' nonIndexedName (conT ''Generic) []-    , instanceD' nonIndexedName (conT ''ABIType) [funD' 'isDynamic [] [|const False|]]-    , instanceD' nonIndexedName (conT ''ABIGet) []+    , instanceD' nonIndexedName (conT ''AbiType) [funD' 'isDynamic [] [|const False|]]+    , instanceD' nonIndexedName (conT ''AbiGet) []     , dataD' allName (recC allName (map (\(n, a) -> ((\(b,t) -> return (n,b,t)) <=< toBang <=< typeQ $ a)) allArgs)) derivingD     , instanceD' allName (conT ''Generic) []     , instanceD (cxt [])@@ -187,6 +203,7 @@         [funD' 'def [] [|Filter Nothing Latest Latest $ Just topics|] ]     ]   where+    name = if Char.toLower (T.head uncheckedName) == Char.toUpper (T.head uncheckedName) then "EvT" <> uncheckedName else uncheckedName     topics    = [Just (T.unpack $ eventId ev)] <> replicate (length indexedArgs) Nothing     toBang ty = bangType (bang sourceNoUnpack sourceStrict) (return ty)     tag (n, ty) = AppT (AppT (ConT ''Tagged) (LitT $ NumTyLit n)) <$> typeQ ty@@ -199,16 +216,17 @@     allName = mkName $ toUpperFirst (T.unpack name)     derivingD = [''Show, ''Eq, ''Ord, ''GHC.Generic] +-- TODO change this type name also -- | Method delcarations maker mkDecl fun@(DFunction name constant inputs outputs) = (++)   <$> funWrapper constant fnName dataName inputs outputs   <*> sequence         [ dataD' dataName (normalC dataName bangInput) derivingD         , instanceD' dataName (conT ''Generic) []-        , instanceD' dataName (conT ''ABIType)+        , instanceD' dataName (conT ''AbiType)           [funD' 'isDynamic [] [|const False|]]-        , instanceD' dataName (conT ''ABIPut) []-        , instanceD' dataName (conT ''ABIGet) []+        , instanceD' dataName (conT ''AbiPut) []+        , instanceD' dataName (conT ''AbiGet) []         , instanceD' dataName (conT ''Method)           [funD' 'selector [] [|const mIdent|]]         ]@@ -220,6 +238,28 @@  mkDecl _ = return [] +mkContractDecl :: Text -> Text -> Text -> Declaration -> DecsQ+mkContractDecl name a b (DConstructor inputs) = sequence+    [ dataD' dataName (normalC dataName bangInput) derivingD+    , instanceD' dataName (conT ''Generic) []+    , instanceD' dataName (conT ''AbiType)+        [funD' 'isDynamic [] [|const False|]]+    , instanceD' dataName (conT ''AbiPut) []+    , instanceD' dataName (conT ''Method)+        [funD' 'selector [] [|convert . Contract.bytecode|]]+    , instanceD' dataName (conT ''Contract.Contract)+        [ funD' 'Contract.abi [] [|const abiString|]+        , funD' 'Contract.bytecode [] [|const bytecodeString|]+        ]+    ]+  where abiString = T.unpack a+        bytecodeString = T.unpack b+        dataName = mkName (toUpperFirst (T.unpack $ name <> "Contract"))+        bangInput = fmap funBangType inputs+        derivingD = [''Show, ''Eq, ''Ord, ''GHC.Generic]++mkContractDecl _ _ _ _ = return []+ -- | this function gives appropriate names for the accessors in the following way -- | argName -> evArgName -- | arg_name -> evArg_name@@ -231,15 +271,15 @@     prefixStr = toLowerFirst . T.unpack $ prefix     go :: Int -> [(Text, Text)] -> [(Name, Text)]     go _ [] = []-    go i ((h, ty) : tail') = if T.null h-                        then (mkName $ prefixStr ++ show i, ty) : go (i + 1) tail'-                        else (mkName . (++ "_") . (++) prefixStr . toUpperFirst . T.unpack $ h, ty) : go (i + 1) tail'+    go i ((h, ty) : tail')+        | T.null h  = (mkName $ prefixStr ++ show i, ty) : go (i + 1) tail'+        | otherwise = (mkName . (++ "_") . (++) prefixStr . toUpperFirst . T.unpack $ h, ty) : go (i + 1) tail'  escape :: [Declaration] -> [Declaration] escape = escapeEqualNames . fmap escapeReservedNames  escapeEqualNames :: [Declaration] -> [Declaration]-escapeEqualNames = concat . fmap go . group . sort+escapeEqualNames = concatMap go . group . sort   where go []       = []         go (x : xs) = x : zipWith appendToName xs hats         hats = [T.replicate n "'" | n <- [1..]]@@ -262,20 +302,38 @@                       , "infix", "infixl", "infixr"                       , "let", "in", "mdo", "module"                       , "newtype", "proc", "qualified"-                      , "rec", "type", "where"]+                      , "rec", "type", "where"+                      ] --- | ABI to declarations converter+constructorSpec :: String -> Maybe (Text, Text, Text, Declaration)+constructorSpec str = do+    name     <- str ^? key "contractName" . _String+    abiValue <- str ^? key "abi"+    bytecode <- str ^? key "bytecode" . _String+    decl     <- filter isContructor . unAbi <$> str ^? key "abi" . _JSON+    return (name, jsonEncode abiValue, bytecode, toConstructor decl)+  where+    jsonEncode = LT.toStrict . LT.decodeUtf8 . Aeson.encode+    isContructor (DConstructor _) = True+    isContructor _                = False+    toConstructor []  = DConstructor []+    toConstructor [a] = a+    toConstructor _   = error "Broken ABI: more that one constructor"++-- | Abi to declarations converter quoteAbiDec :: String -> DecsQ-quoteAbiDec abi_string =-    case eitherDecode abi_lbs of-        Left e                -> fail $ "Error: " ++ show e-        Right (ContractABI a) -> concat <$> mapM mkDecl (escape a)-  where abi_lbs = LT.encodeUtf8 (LT.pack abi_string)+quoteAbiDec str =+    case str ^? _JSON <|> str ^? key "abi" . _JSON of+        Nothing                 -> fail "Unable to decode contract ABI"+        Just (ContractAbi decs) -> do+            funEvDecs <- concat <$> mapM mkDecl (escape decs)+            case constructorSpec str of+                Nothing -> return funEvDecs+                Just (a, b, c, d) -> (funEvDecs ++) <$> mkContractDecl a b c d --- | ABI information string+-- | Abi information string quoteAbiExp :: String -> ExpQ-quoteAbiExp abi_string = stringE $-    case eitherDecode abi_lbs of-        Left e  -> "Error: " ++ show e-        Right a -> show (a :: ContractABI)-  where abi_lbs = LT.encodeUtf8 (LT.pack abi_string)+quoteAbiExp str =+    case str ^? _JSON <|> str ^? key "abi" . _JSON of+        Nothing                -> fail "Unable to decode contract ABI"+        Just a@(ContractAbi _) -> stringE (show a)
+ src/Network/Ethereum/Ens.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE DataKinds         #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module      :  Network.Ethereum.Ens+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- ENS offers a secure & decentralised way to address resources both on+-- and off the blockchain using simple, human-readable names.+--+-- This module provide basic ENS resolvers.+--++module Network.Ethereum.Ens where++import           Crypto.Hash                         (Digest, Keccak_256, hash)+import           Data.ByteArray                      (convert, zero)+import           Data.ByteArray.Sized                (unsafeFromByteArrayAccess)+import           Data.ByteString                     (ByteString)+import           Data.ByteString.Char8               (split)+import           Data.Monoid                         ((<>))+import           Lens.Micro                          ((.~))++import           Data.Solidity.Prim                  (Address, BytesN)+import           Network.Ethereum.Account.Class      (Account)+import           Network.Ethereum.Account.Internal   (AccountT, to, withParam)+import qualified Network.Ethereum.Ens.PublicResolver as Resolver+import qualified Network.Ethereum.Ens.Registry       as Reg+import           Network.JsonRpc.TinyClient          (JsonRpc)++-- | Namehash algorithm+-- http://docs.ens.domains/en/latest/implementers.html#algorithm+namehash :: ByteString+         -- ^ Domain name+         -> BytesN 32+         -- ^ Associated ENS node+namehash =+    unsafeFromByteArrayAccess . foldr algo (zero 32) . split '.'+  where+    algo a b = sha3 (b <> sha3 a)+    sha3 :: ByteString -> ByteString+    sha3 bs = convert (hash bs :: Digest Keccak_256)++-- | Get address of ENS domain+resolve :: (JsonRpc m, Account p (AccountT p))+        => ByteString+        -- ^ Domain name+        -> AccountT p m Address+        -- ^ Associated address+resolve name = do+    r <- ensRegistry $ Reg.resolver node+    withParam (to .~ r) $ Resolver.addr node+  where+    node = namehash name+    ensRegistry = withParam $ to .~ "0x314159265dD8dbb310642f98f50C066173C1259b"
+ src/Network/Ethereum/Ens/PublicResolver.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE QuasiQuotes           #-}++-- |+-- Module      :  Network.Ethereum.Ens.PublicResolver+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Ethereum Name System public resolver smart contract.+--++module Network.Ethereum.Ens.PublicResolver where++import           Network.Ethereum.Contract.TH++[abi|[{"constant":true,"inputs":[{"name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"name":"contentType","type":"uint256"},{"name":"data","type":"bytes"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"x","type":"bytes32"},{"name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"content","outputs":[{"name":"ret","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"addr","outputs":[{"name":"ret","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentType","type":"uint256"},{"name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"name","outputs":[{"name":"ret","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"hash","type":"bytes32"}],"name":"setContent","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"name":"x","type":"bytes32"},{"name":"y","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"addr","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"ensAddr","type":"address"}],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"hash","type":"bytes32"}],"name":"ContentChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"x","type":"bytes32"},{"indexed":false,"name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"}]|]
+ src/Network/Ethereum/Ens/Registry.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE QuasiQuotes           #-}++-- |+-- Module      :  Network.Ethereum.Ens.Registry+-- Copyright   :  Alexander Krupenkin 2018+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- Ethereum Name System registry smart contract.+--++module Network.Ethereum.Ens.Registry where++import           Network.Ethereum.Contract.TH++[abi|[{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"label","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"ttl","outputs":[{"name":"","type":"uint64"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"label","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"resolver","type":"address"}],"name":"NewResolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"ttl","type":"uint64"}],"name":"NewTTL","type":"event"}]|]
src/Network/Ethereum/Unit.hs view
@@ -47,19 +47,22 @@ -- @ -- -module Network.Ethereum.Unit (-    Unit(..)-  , UnitSpec(..)-  , Wei-  , Babbage-  , Lovelace-  , Shannon-  , Szabo-  , Finney-  , Ether-  , KEther-  ) where+module Network.Ethereum.Unit+    (+    -- * The @Unit@ type class+      Unit(..) +    -- * Ethereum value metrics+    , Wei+    , Babbage+    , Lovelace+    , Shannon+    , Szabo+    , Finney+    , Ether+    , KEther+    ) where+ import           Data.Proxy                      (Proxy (..)) import           Data.Text.Lazy                  (Text, unpack) import           GHC.Generics                    (Generic)@@ -71,13 +74,10 @@ -- | Ethereum value unit class (Read a, Show a, UnitSpec a, Fractional a) => Unit a where     -- | Make a value from integer wei-    fromWei :: Integer -> a+    fromWei :: Integral b => b -> a+     -- | Convert a value to integer wei-    toWei :: a -> Integer-    -- | Conversion beween two values-    convert :: Unit b => a -> b-    {-# INLINE convert #-}-    convert = fromWei . toWei+    toWei :: Integral b => a -> b  -- | Unit specification class UnitSpec a where@@ -92,8 +92,8 @@ mkValue = MkValue . round . (* divider (Proxy :: Proxy a))  instance UnitSpec a => Unit (Value a) where-    fromWei = MkValue-    toWei   = unValue+    fromWei = MkValue . toInteger+    toWei   = fromInteger . unValue  instance UnitSpec a => UnitSpec (Value a) where     divider = const $ divider (Proxy :: Proxy a)
src/Network/Ethereum/Web3.hs view
@@ -17,33 +17,28 @@ -- Web3 Haskell library currently use JSON-RPC over HTTP to access node functionality. -- -module Network.Ethereum.Web3 (--  -- ** Monad as base of any Ethereum node communication-    Web3-  , runWeb3--  -- ** Basic transaction sending-  , sendTx-  , Call(..)+module Network.Ethereum.Web3+    (+    -- * Base monad for any Ethereum node communication+      Web3+    , runWeb3 -  -- ** Basic event listening-  , EventAction(..)-  , event-  , event'+    -- * Basic transaction sending+    , module Account -  -- ** Primitive data types-  , module Network.Ethereum.ABI.Prim+    -- * Basic event listening+    , EventAction(..)+    , event -  -- ** Metric unit system-  , module Network.Ethereum.Unit+    -- * Primitive data types+    , module Prim -  ) where+    -- * Metric unit system+    , module Unit+    ) where -import           Network.Ethereum.ABI.Prim-import           Network.Ethereum.Contract.Event  (EventAction (..), event,-                                                   event')-import           Network.Ethereum.Contract.Method (sendTx)-import           Network.Ethereum.Unit-import           Network.Ethereum.Web3.Provider   (Web3, runWeb3)-import           Network.Ethereum.Web3.Types      (Call (..))+import           Data.Solidity.Prim              as Prim+import           Network.Ethereum.Account        as Account+import           Network.Ethereum.Api.Provider   (Web3, runWeb3)+import           Network.Ethereum.Contract.Event (EventAction (..), event)+import           Network.Ethereum.Unit           as Unit
− src/Network/Ethereum/Web3/Eth.hs
@@ -1,250 +0,0 @@-{-# LANGUAGE DataKinds         #-}-{-# LANGUAGE OverloadedStrings #-}---- |--- Module      :  Network.Ethereum.Web3.Eth--- Copyright   :  Alexander Krupenkin 2016--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  unknown------ Ethereum node JSON-RPC API methods with `eth_` prefix.-----module Network.Ethereum.Web3.Eth where--import           Data.Text                         (Text)-import           Network.Ethereum.ABI.Prim.Address (Address)-import           Network.Ethereum.ABI.Prim.Bytes   (Bytes, BytesN)-import           Network.Ethereum.Web3.Provider    (Web3)-import           Network.Ethereum.Web3.Types       (Block, Call, Change,-                                                    DefaultBlock, Filter, Hash,-                                                    Quantity, SyncingState,-                                                    Transaction, TxReceipt)-import           Network.JsonRpc.TinyClient        (remote)---- | Returns the current ethereum protocol version.-protocolVersion :: Web3 Text-{-# INLINE protocolVersion #-}-protocolVersion = remote "eth_protocolVersion"---- | Returns an object with data about the sync status or false.-syncing :: Web3 SyncingState-{-# INLINE syncing #-}-syncing = remote "eth_syncing"---- | Returns the client coinbase address.-coinbase :: Web3 Address-{-# INLINE coinbase #-}-coinbase = remote "eth_coinbase"---- | Returns true if client is actively mining new blocks.-mining :: Web3 Bool-{-# INLINE mining #-}-mining = remote "eth_mining"---- | Returns the number of hashes per second that the node is mining with.-hashrate :: Web3 Quantity-{-# INLINE hashrate #-}-hashrate = remote "eth_hashrate"---- | Returns the value from a storage position at a given address.-getStorageAt :: Address -> Quantity -> DefaultBlock -> Web3 (BytesN 32)-{-# INLINE getStorageAt #-}-getStorageAt = remote "eth_getStorageAt"---- | Returns the number of transactions sent from an address.-getTransactionCount :: Address -> DefaultBlock -> Web3 Quantity-{-# INLINE getTransactionCount #-}-getTransactionCount = remote "eth_getTransactionCount"---- | Returns the number of transactions in a block from a block matching the given block hash.-getBlockTransactionCountByHash :: Hash -> Web3 Quantity-{-# INLINE getBlockTransactionCountByHash #-}-getBlockTransactionCountByHash = remote "eth_getBlockTransactionCountByHash"---- | Returns the number of transactions in a block matching the--- given block number.-getBlockTransactionCountByNumber :: Quantity -> Web3 Quantity-{-# INLINE getBlockTransactionCountByNumber #-}-getBlockTransactionCountByNumber = remote "eth_getBlockTransactionCountByNumber"---- | Returns the number of uncles in a block from a block matching the given--- block hash.-getUncleCountByBlockHash :: Hash -> Web3 Quantity-{-# INLINE getUncleCountByBlockHash #-}-getUncleCountByBlockHash = remote "eth_getUncleCountByBlockHash"---- | Returns the number of uncles in a block from a block matching the given--- block number.-getUncleCountByBlockNumber :: Quantity -> Web3 Quantity-{-# INLINE getUncleCountByBlockNumber #-}-getUncleCountByBlockNumber = remote "eth_getUncleCountByBlockNumber"---- | Returns code at a given address.-getCode :: Address -> DefaultBlock -> Web3 Bytes-{-# INLINE getCode #-}-getCode = remote "eth_getCode"---- | Returns an Ethereum specific signature with:--- sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).-sign :: Address -> Bytes -> Web3 Bytes-{-# INLINE sign #-}-sign = remote "eth_sign"---- | Creates new message call transaction or a contract creation,--- if the data field contains code.-sendTransaction :: Call -> Web3 Hash-{-# INLINE sendTransaction #-}-sendTransaction = remote "eth_sendTransaction"---- | Creates new message call transaction or a contract creation for signed--- transactions.-sendRawTransaction :: Bytes -> Web3 Hash-{-# INLINE sendRawTransaction #-}-sendRawTransaction = remote "eth_sendRawTransaction"---- | Returns the balance of the account of given address.-getBalance :: Address -> DefaultBlock -> Web3 Quantity-{-# INLINE getBalance #-}-getBalance = remote "eth_getBalance"---- | Creates a filter object, based on filter options, to notify when the--- state changes (logs). To check if the state has changed, call--- 'getFilterChanges'.-newFilter :: Filter e -> Web3 Quantity-{-# INLINE newFilter #-}-newFilter = remote "eth_newFilter"---- | Polling method for a filter, which returns an array of logs which--- occurred since last poll.-getFilterChanges :: Quantity -> Web3 [Change]-{-# INLINE getFilterChanges #-}-getFilterChanges = remote "eth_getFilterChanges"---- | Uninstalls a filter with given id.--- Should always be called when watch is no longer needed.-uninstallFilter :: Quantity -> Web3 Bool-{-# INLINE uninstallFilter #-}-uninstallFilter = remote "eth_uninstallFilter"---- | Returns an array of all logs matching a given filter object.-getLogs :: Filter e -> Web3 [Change]-{-# INLINE getLogs #-}-getLogs = remote "eth_getLogs"---- | Executes a new message call immediately without creating a--- transaction on the block chain.-call :: Call -> DefaultBlock -> Web3 Bytes-{-# INLINE call #-}-call = remote "eth_call"---- | Makes a call or transaction, which won't be added to the blockchain and--- returns the used gas, which can be used for estimating the used gas.-estimateGas :: Call -> Web3 Quantity-{-# INLINE estimateGas #-}-estimateGas = remote "eth_estimateGas"---- | Returns information about a block by hash.-getBlockByHash :: Hash -> Web3 Block-{-# INLINE getBlockByHash #-}-getBlockByHash = flip (remote "eth_getBlockByHash") True---- | Returns information about a block by block number.-getBlockByNumber :: Quantity -> Web3 Block-{-# INLINE getBlockByNumber #-}-getBlockByNumber = flip (remote "eth_getBlockByNumber") True---- | Returns the information about a transaction requested by transaction hash.-getTransactionByHash :: Hash -> Web3 (Maybe Transaction)-{-# INLINE getTransactionByHash #-}-getTransactionByHash = remote "eth_getTransactionByHash"---- | Returns information about a transaction by block hash and transaction index position.-getTransactionByBlockHashAndIndex :: Hash -> Quantity -> Web3 (Maybe Transaction)-{-# INLINE getTransactionByBlockHashAndIndex #-}-getTransactionByBlockHashAndIndex = remote "eth_getTransactionByBlockHashAndIndex"---- | Returns information about a transaction by block number and transaction--- index position.-getTransactionByBlockNumberAndIndex :: DefaultBlock -> Quantity -> Web3 (Maybe Transaction)-{-# INLINE getTransactionByBlockNumberAndIndex #-}-getTransactionByBlockNumberAndIndex = remote "eth_getTransactionByBlockNumberAndIndex"---- | Returns the receipt of a transaction by transaction hash.-getTransactionReceipt :: Hash -> Web3 (Maybe TxReceipt)-{-# INLINE getTransactionReceipt #-}-getTransactionReceipt = remote "eth_getTransactionReceipt"---- | Returns a list of addresses owned by client.-accounts :: Web3 [Address]-{-# INLINE accounts #-}-accounts = remote "eth_accounts"---- | Creates a filter in the node, to notify when a new block arrives.-newBlockFilter :: Web3 Quantity-{-# INLINE newBlockFilter #-}-newBlockFilter = remote "eth_newBlockFilter"---- | Polling method for a block filter, which returns an array of block hashes--- occurred since last poll.-getBlockFilterChanges :: Quantity -> Web3 [Hash]-{-# INLINE getBlockFilterChanges #-}-getBlockFilterChanges = remote "eth_getFilterChanges"---- | Returns the number of most recent block.-blockNumber :: Web3 Quantity-{-# INLINE blockNumber #-}-blockNumber = remote "eth_blockNumber"---- | Returns the current price per gas in wei.-gasPrice :: Web3 Quantity-{-# INLINE gasPrice #-}-gasPrice = remote "eth_gasPrice"---- | Returns information about a uncle of a block by hash and uncle index--- position.-getUncleByBlockHashAndIndex :: Hash -> Quantity -> Web3 Block-{-# INLINE getUncleByBlockHashAndIndex #-}-getUncleByBlockHashAndIndex = remote "eth_getUncleByBlockHashAndIndex"---- | Returns information about a uncle of a block by number and uncle index--- position.-getUncleByBlockNumberAndIndex :: DefaultBlock -> Quantity -> Web3 Block-{-# INLINE getUncleByBlockNumberAndIndex #-}-getUncleByBlockNumberAndIndex = remote "eth_getUncleByBlockNumberAndIndex"---- | Creates a filter in the node, to notify when new pending transactions arrive. To check if the state has changed, call getFilterChanges. Returns a FilterId.-newPendingTransactionFilter :: Web3 Quantity-{-# INLINE newPendingTransactionFilter #-}-newPendingTransactionFilter = remote "eth_newPendingTransactionFilter"---- | Returns an array of all logs matching filter with given id.-getFilterLogs :: Quantity -> Web3 [Change]-{-# INLINE getFilterLogs #-}-getFilterLogs = remote "eth_getFilterLogs"---- | Returns the hash of the current block, the seedHash, and the boundary--- condition to be met ("target").-getWork :: Web3 [Bytes]-{-# INLINE getWork #-}-getWork = remote "eth_getWork"---- | Used for submitting a proof-of-work solution.--- Parameters:--- 1. DATA, 8 Bytes - The nonce found (64 bits)--- 2. DATA, 32 Bytes - The header's pow-hash (256 bits)--- 3. DATA, 32 Bytes - The mix digest (256 bits)-submitWork :: BytesN 8 -> BytesN 32 -> BytesN 32 -> Web3 Bool-{-# INLINE submitWork #-}-submitWork = remote "eth_submitWork"---- | Used for submitting mining hashrate.--- Parameters:--- 1. Hashrate, a hexadecimal string representation (32 bytes) of the hash rate--- 2. ID, String - A random hexadecimal(32 bytes) ID identifying the client-submitHashrate :: BytesN 32 -> BytesN 32 -> Web3 Bool-{-# INLINE submitHashrate #-}-submitHashrate = remote "eth_submitHashrate"
− src/Network/Ethereum/Web3/Net.hs
@@ -1,35 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- |--- Module      :  Network.Ethereum.Web3.Net--- Copyright   :  Alexander Krupenkin 2016--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  unknown------ Ethereum node JSON-RPC API methods with `net_` prefix.-----module Network.Ethereum.Web3.Net where--import           Data.Text                      (Text)-import           Network.Ethereum.Web3.Provider (Web3)-import           Network.Ethereum.Web3.Types    (Quantity)-import           Network.JsonRpc.TinyClient     (remote)---- | Returns the current network id.-version :: Web3 Text-{-# INLINE version #-}-version = remote "net_version"---- | Returns true if client is actively listening for network connections.-listening :: Web3 Bool-{-# INLINE listening #-}-listening = remote "net_listening"---- | Returns number of peers currently connected to the client.-peerCount :: Web3 Quantity-{-# INLINE peerCount #-}-peerCount = remote "net_peerCount"
− src/Network/Ethereum/Web3/Provider.hs
@@ -1,94 +0,0 @@-{-# LANGUAGE CPP                        #-}-{-# LANGUAGE DeriveGeneric              #-}-{-# LANGUAGE FlexibleInstances          #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses      #-}---- |--- Module      :  Network.Ethereum.Web3.Provider--- Copyright   :  Alexander Krupenkin 2016--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  portable------ Web3 service provider.-----module Network.Ethereum.Web3.Provider where--import           Control.Concurrent.Async   (Async, async)-import           Control.Exception          (Exception, try)-import           Control.Monad.Catch        (MonadThrow)-import           Control.Monad.IO.Class     (MonadIO (..))-import           Control.Monad.Reader       (MonadReader (..))-import           Control.Monad.Trans.Reader (ReaderT, mapReaderT, runReaderT)-import           Data.Aeson                 (FromJSON)-import           Data.Default               (Default (..))-import           GHC.Generics               (Generic)-import           Network.HTTP.Client        (Manager, newManager)--#ifdef TLS_MANAGER-import           Network.HTTP.Client.TLS    (tlsManagerSettings)-#else-import           Network.HTTP.Client        (defaultManagerSettings)-#endif--import           Network.JsonRpc.TinyClient (Remote, ServerUri)---- | Any communication with Ethereum node wrapped with 'Web3' monad-newtype Web3 a = Web3 { unWeb3 :: ReaderT (ServerUri, Manager) IO a }-    deriving (Functor, Applicative, Monad, MonadIO, MonadThrow)--instance MonadReader (ServerUri, Manager) Web3 where-    ask = Web3 ask-    local f = Web3 . local f . unWeb3--instance FromJSON a => Remote Web3 (Web3 a)---- | Some peace of error response-data Web3Error-  = JsonRpcFail !String-  -- ^ JSON-RPC communication error-  | ParserFail  !String-  -- ^ Error in parser state-  | UserFail    !String-  -- ^ Common head for user errors-  deriving (Show, Eq, Generic)--instance Exception Web3Error----TODO: Change to `HttpProvider ServerUri | IpcProvider FilePath` to support IPC--- | Web3 Provider-data Provider = HttpProvider ServerUri-  deriving (Show, Eq, Generic)--instance Default Provider where-  def = HttpProvider "http://localhost:8545"---- | 'Web3' monad runner, using the supplied Manager-runWeb3With :: MonadIO m => Manager -> Provider -> Web3 a -> m (Either Web3Error a)-runWeb3With manager (HttpProvider uri) f =-    liftIO . try .  flip runReaderT (uri, manager) . unWeb3 $ f---- | 'Web3' monad runner-runWeb3' :: MonadIO m => Provider -> Web3 a -> m (Either Web3Error a)-runWeb3' provider f = do-    manager <- liftIO $-#ifdef TLS_MANAGER-        newManager tlsManagerSettings-#else-        newManager defaultManagerSettings-#endif-    runWeb3With manager provider f---- | 'Web3' runner for default provider-runWeb3 :: MonadIO m => Web3 a -> m (Either Web3Error a)-{-# INLINE runWeb3 #-}-runWeb3 = runWeb3' def---- | Fork 'Web3' with the same 'Provider'-forkWeb3 :: Web3 a -> Web3 (Async a)-{-# INLINE forkWeb3 #-}-forkWeb3 = Web3 . mapReaderT async . unWeb3
− src/Network/Ethereum/Web3/Types.hs
@@ -1,315 +0,0 @@-{-# LANGUAGE DataKinds                  #-}-{-# LANGUAGE DeriveDataTypeable         #-}-{-# LANGUAGE DeriveGeneric              #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings          #-}-{-# LANGUAGE TemplateHaskell            #-}---- |--- Module      :  Network.Ethereum.Web3.Types--- Copyright   :  Alexander Krupenkin 2016--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  portable------ Ethereum generic JSON-RPC types.-----module Network.Ethereum.Web3.Types where--import           Data.Aeson                        (FromJSON (..), Options (fieldLabelModifier, omitNothingFields),-                                                    ToJSON (..),-                                                    Value (Bool, String),-                                                    defaultOptions, object,-                                                    (.=))-import           Data.Aeson.TH                     (deriveJSON)-import           Data.Default                      (Default (..))-import           Data.Monoid                       ((<>))-import           Data.Ord                          (Down (..))-import           Data.String                       (IsString (..))-import qualified Data.Text                         as T (pack)-import qualified Data.Text.Lazy.Builder            as B (toLazyText)-import qualified Data.Text.Lazy.Builder.Int        as B (hexadecimal)-import qualified Data.Text.Read                    as R (decimal, hexadecimal)-import           GHC.Generics                      (Generic)--import           Data.String.Extra                 (toLowerFirst)-import           Network.Ethereum.ABI.Prim.Address (Address)-import           Network.Ethereum.ABI.Prim.Bytes   (Bytes, BytesN)-import           Network.Ethereum.Unit---- | 32 byte type synonym for transaction and block hashes.-type Hash = BytesN 32---- | Should be viewed as type to representing QUANTITY in Web3 JSON RPC docs------  When encoding QUANTITIES (integers, numbers): encode as hex, prefix with "0x",---  the most compact representation (slight exception: zero should be represented as "0x0").---  Examples:------  0x41 (65 in decimal)---  0x400 (1024 in decimal)---  WRONG: 0x (should always have at least one digit - zero is "0x0")---  WRONG: 0x0400 (no leading zeroes allowed)---  WRONG: ff (must be prefixed 0x)-newtype Quantity = Quantity { unQuantity :: Integer }-    deriving (Read, Num, Real, Enum, Eq, Ord, Generic)--instance Show Quantity where-    show = show . unQuantity--instance IsString Quantity where-    fromString ('0' : 'x' : hex) =-        case R.hexadecimal (T.pack hex) of-            Right (x, "") -> Quantity x-            _             -> error "Unable to parse Quantity!"-    fromString str =-        case R.decimal (T.pack str) of-            Right (x, "") -> Quantity x-            _             -> error "Unable to parse Quantity!"--instance ToJSON Quantity where-    toJSON (Quantity x) =-        let hexValue = B.toLazyText (B.hexadecimal x)-        in  toJSON ("0x" <> hexValue)--instance FromJSON Quantity where-    parseJSON (String v) =-        case R.hexadecimal v of-            Right (x, "") -> return (Quantity x)-            _             -> fail "Unable to parse Quantity"-    parseJSON _ = fail "Quantity may only be parsed from a JSON String"--instance Fractional Quantity where-    (/) a b = Quantity $ div (unQuantity a) (unQuantity b)-    fromRational = Quantity . floor--instance Unit Quantity where-    fromWei = Quantity-    toWei = unQuantity--instance UnitSpec Quantity where-    divider = const 1-    name = const "quantity"---- | An object with sync status data.-data SyncActive = SyncActive-  { syncStartingBlock :: !Quantity-  -- ^ QUANTITY - The block at which the import started (will only be reset, after the sync reached his head).-  , syncCurrentBlock  :: !Quantity-  -- ^ QUANTITY - The current block, same as eth_blockNumber.-  , syncHighestBlock  :: !Quantity-  -- ^ QUANTITY - The estimated highest block.-  } deriving (Eq, Generic, Show)--$(deriveJSON (defaultOptions-    { fieldLabelModifier = toLowerFirst . drop 4 }) ''SyncActive)---- | Sync state pulled by low-level call 'eth_syncing'.-data SyncingState = Syncing SyncActive | NotSyncing-    deriving (Eq, Generic, Show)--instance FromJSON SyncingState where-    parseJSON (Bool _) = pure NotSyncing-    parseJSON v        = Syncing <$> parseJSON v---- | Changes pulled by low-level call 'eth_getFilterChanges', 'eth_getLogs',--- and 'eth_getFilterLogs'-data Change = Change-  { changeLogIndex         :: !(Maybe Quantity)-  -- ^ QUANTITY - integer of the log index position in the block. null when its pending log.-  , changeTransactionIndex :: !(Maybe Quantity)-  -- ^ QUANTITY - integer of the transactions index position log was created from. null when its pending log.-  , changeTransactionHash  :: !(Maybe Hash)-  -- ^ DATA, 32 Bytes - hash of the transactions this log was created from. null when its pending log.-  , changeBlockHash        :: !(Maybe Hash)-  -- ^ DATA, 32 Bytes - hash of the block where this log was in. null when its pending. null when its pending log.-  , changeBlockNumber      :: !(Maybe Quantity)-  -- ^ QUANTITY - the block number where this log was in. null when its pending. null when its pending log.-  , changeAddress          :: !Address-  -- ^ DATA, 20 Bytes - address from which this log originated.-  , changeData             :: !Bytes-  -- ^ DATA - contains one or more 32 Bytes non-indexed arguments of the log.-  , changeTopics           :: ![BytesN 32]-  -- ^ Array of DATA - Array of 0 to 4 32 Bytes DATA of indexed log arguments.-  -- (In solidity: The first topic is the hash of the signature of the event-  -- (e.g. Deposit(address, bytes32, uint256)), except you declared the event with-  -- the anonymous specifier.)-  } deriving (Eq, Show, Generic)--$(deriveJSON (defaultOptions-    { fieldLabelModifier = toLowerFirst . drop 6 }) ''Change)---- | The contract call params.-data Call = Call-  { callFrom     :: !(Maybe Address)-  -- ^ DATA, 20 Bytes - The address the transaction is send from.-  , callTo       :: !(Maybe Address)-  -- ^ DATA, 20 Bytes - (optional when creating new contract) The address the transaction is directed to.-  , callGas      :: !(Maybe Quantity)-  -- ^ QUANTITY - (optional, default: 3000000) Integer of the gas provided for the transaction execution. It will return unused gas.-  , callGasPrice :: !(Maybe Quantity)-  -- ^ QUANTITY - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas.-  , callValue    :: !(Maybe Quantity)-  -- ^ QUANTITY - (optional) Integer of the value sent with this transaction.-  , callData     :: !(Maybe Bytes)-  -- ^ DATA - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters.-  , callNonce    :: !(Maybe Quantity)-  -- ^ QUANTITY - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.-  } deriving (Eq, Show, Generic)--$(deriveJSON (defaultOptions-    { fieldLabelModifier = toLowerFirst . drop 4-    , omitNothingFields = True }) ''Call)--instance Default Call where-    def = Call Nothing Nothing (Just 3000000) Nothing (Just 0) Nothing Nothing---- | The state of blockchain for contract call.-data DefaultBlock = BlockWithNumber Quantity-                  | Earliest-                  | Latest-                  | Pending-    deriving (Eq, Show, Generic)--instance ToJSON DefaultBlock where-    toJSON (BlockWithNumber bn) = toJSON bn-    toJSON parameter            = toJSON . toLowerFirst . show $ parameter---- | Low-level event filter data structure.-data Filter e = Filter-  { filterAddress   :: !(Maybe [Address])-  -- ^ DATA|Array, 20 Bytes - (optional) Contract address or a list of addresses from which logs should originate.-  , filterFromBlock :: !DefaultBlock-  -- ^ QUANTITY|TAG - (optional, default: "latest") Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions.-  , filterToBlock   :: !DefaultBlock-  -- ^ QUANTITY|TAG - (optional, default: "latest") Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions.-  , filterTopics    :: !(Maybe [Maybe (BytesN 32)])-  -- ^ Array of DATA, - (optional) Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with "or" options.-  -- Topics are order-dependent. A transaction with a log with topics [A, B] will be matched by the following topic filters:-  -- * [] "anything"-  -- * [A] "A in first position (and anything after)"-  -- * [null, B] "anything in first position AND B in second position (and anything after)"-  -- * [A, B] "A in first position AND B in second position (and anything after)"-  -- * [[A, B], [A, B]] "(A OR B) in first position AND (A OR B) in second position (and anything after)"-  } deriving (Eq, Show, Generic)--instance ToJSON (Filter e) where-    toJSON f = object [ "address"   .= filterAddress f-                      , "fromBlock" .= filterFromBlock f-                      , "toBlock"   .= filterToBlock f-                      , "topics"    .= filterTopics f ]--instance Ord DefaultBlock where-    compare Pending Pending                         = EQ-    compare Latest Latest                           = EQ-    compare Earliest Earliest                       = EQ-    compare (BlockWithNumber a) (BlockWithNumber b) = compare a b-    compare _ Pending                               = LT-    compare Pending Latest                          = GT-    compare _ Latest                                = LT-    compare Earliest _                              = LT-    compare a b                                     = compare (Down b) (Down a)---- | The Receipt of a Transaction-data TxReceipt = TxReceipt-  { receiptTransactionHash   :: !Hash-  -- ^ DATA, 32 Bytes - hash of the transaction.-  , receiptTransactionIndex  :: !Quantity-  -- ^ QUANTITY - index of the transaction.-  , receiptBlockHash         :: !(Maybe Hash)-  -- ^ DATA, 32 Bytes - hash of the block where this transaction was in. null when its pending.-  , receiptBlockNumber       :: !(Maybe Quantity)-  -- ^ QUANTITY - block number where this transaction was in. null when its pending.-  , receiptCumulativeGasUsed :: !Quantity-  -- ^ QUANTITY - The total amount of gas used when this transaction was executed in the block.-  , receiptGasUsed           :: !Quantity-  -- ^ QUANTITY - The amount of gas used by this specific transaction alone.-  , receiptContractAddress   :: !(Maybe Address)-  -- ^ DATA, 20 Bytes - The contract address created, if the transaction was a contract creation, otherwise null.-  , receiptLogs              :: ![Change]-  -- ^ Array - Array of log objects, which this transaction generated.-  , receiptLogsBloom         :: !Bytes-  -- ^ DATA, 256 Bytes - Bloom filter for light clients to quickly retrieve related logs.-  , receiptStatus            :: !(Maybe Quantity)-  -- ^ QUANTITY either 1 (success) or 0 (failure)-  } deriving (Show, Generic)--$(deriveJSON (defaultOptions-    { fieldLabelModifier = toLowerFirst . drop 7 }) ''TxReceipt)---- | Transaction information.-data Transaction = Transaction-  { txHash             :: !Hash-  -- ^ DATA, 32 Bytes - hash of the transaction.-  , txNonce            :: !Quantity-  -- ^ QUANTITY - the number of transactions made by the sender prior to this one.-  , txBlockHash        :: !(Maybe Hash)-  -- ^ DATA, 32 Bytes - hash of the block where this transaction was in. null when its pending.-  , txBlockNumber      :: !(Maybe Quantity)-  -- ^ QUANTITY - block number where this transaction was in. null when its pending.-  , txTransactionIndex :: !(Maybe Quantity)-  -- ^ QUANTITY - integer of the transactions index position in the block. null when its pending.-  , txFrom             :: !Address-  -- ^ DATA, 20 Bytes - address of the sender.-  , txTo               :: !(Maybe Address)-  -- ^ DATA, 20 Bytes - address of the receiver. null when its a contract creation transaction.-  , txValue            :: !Quantity-  -- ^ QUANTITY - value transferred in Wei.-  , txGasPrice         :: !Quantity-  -- ^ QUANTITY - gas price provided by the sender in Wei.-  , txGas              :: !Quantity-  -- ^ QUANTITY - gas provided by the sender.-  , txInput            :: !Bytes-  -- ^ DATA - the data send along with the transaction.-  } deriving (Eq, Show, Generic)--$(deriveJSON (defaultOptions-    { fieldLabelModifier = toLowerFirst . drop 2 }) ''Transaction)---- | Block information.-data Block = Block-  { blockNumber           :: !(Maybe Quantity)-  -- ^ QUANTITY - the block number. null when its pending block.-  , blockHash             :: !(Maybe Hash)-  -- ^ DATA, 32 Bytes - hash of the block. null when its pending block.-  , blockParentHash       :: !Hash-  -- ^ DATA, 32 Bytes - hash of the parent block.-  , blockNonce            :: !(Maybe Bytes)-  -- ^ DATA, 8 Bytes - hash of the generated proof-of-work. null when its pending block.-  , blockSha3Uncles       :: !(BytesN 32)-  -- ^ DATA, 32 Bytes - SHA3 of the uncles data in the block.-  , blockLogsBloom        :: !(Maybe Bytes)-  -- ^ DATA, 256 Bytes - the bloom filter for the logs of the block. null when its pending block.-  , blockTransactionsRoot :: !(BytesN 32)-  -- ^ DATA, 32 Bytes - the root of the transaction trie of the block.-  , blockStateRoot        :: !(BytesN 32)-  -- ^ DATA, 32 Bytes - the root of the final state trie of the block.-  , blockReceiptRoot      :: !(Maybe (BytesN 32))-  -- ^ DATA, 32 Bytes - the root of the receipts trie of the block.-  , blockMiner            :: !Address-  -- ^ DATA, 20 Bytes - the address of the beneficiary to whom the mining rewards were given.-  , blockDifficulty       :: !Quantity-  -- ^ QUANTITY - integer of the difficulty for this block.-  , blockTotalDifficulty  :: !Quantity-  -- ^ QUANTITY - integer of the total difficulty of the chain until this block.-  , blockExtraData        :: !Bytes-  -- ^ DATA - the "extra data" field of this block.-  , blockSize             :: !Quantity-  -- ^ QUANTITY - integer the size of this block in bytes.-  , blockGasLimit         :: !Quantity-  -- ^ QUANTITY - the maximum gas allowed in this block.-  , blockGasUsed          :: !Quantity-  -- ^ QUANTITY - the total used gas by all transactions in this block.-  , blockTimestamp        :: !Quantity-  -- ^ QUANTITY - the unix timestamp for when the block was collated.-  , blockTransactions     :: ![Transaction]-  -- ^ Array of transaction objects.-  , blockUncles           :: ![Hash]-  -- ^ Array - Array of uncle hashes.-  } deriving (Show, Generic)--$(deriveJSON (defaultOptions-    { fieldLabelModifier = toLowerFirst . drop 5 }) ''Block)
− src/Network/Ethereum/Web3/Web3.hs
@@ -1,31 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- |--- Module      :  Network.Ethereum.Web3.Web3--- Copyright   :  Alexander Krupenkin 2016--- License     :  BSD3------ Maintainer  :  mail@akru.me--- Stability   :  experimental--- Portability :  unknown------ Ethereum node JSON-RPC API methods with `web3_` prefix.-----module Network.Ethereum.Web3.Web3 where--import           Data.Text                       (Text)-import           Network.Ethereum.ABI.Prim.Bytes (Bytes)-import           Network.Ethereum.Web3.Provider  (Web3)-import           Network.Ethereum.Web3.Types     (Hash)-import           Network.JsonRpc.TinyClient      (remote)---- | Returns current node version string.-clientVersion :: Web3 Text-{-# INLINE clientVersion #-}-clientVersion = remote "web3_clientVersion"---- | Returns Keccak-256 (not the standardized SHA3-256) of the given data.-sha3 :: Bytes -> Web3 Hash-{-# INLINE sha3 #-}-sha3 = remote "web3_sha3"
src/Network/JsonRpc/TinyClient.hs view
@@ -1,9 +1,12 @@-{-# LANGUAGE DefaultSignatures      #-}+{-# LANGUAGE CPP                    #-}+{-# LANGUAGE ConstraintKinds        #-} {-# LANGUAGE FlexibleContexts       #-} {-# LANGUAGE FlexibleInstances      #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiParamTypeClasses  #-} {-# LANGUAGE OverloadedStrings      #-}+{-# LANGUAGE RecordWildCards        #-}+{-# LANGUAGE TemplateHaskell        #-} {-# LANGUAGE TypeFamilies           #-} {-# LANGUAGE UndecidableInstances   #-} @@ -20,54 +23,107 @@ -- Functions for implementing the client side of JSON-RPC 2.0. -- See <http://www.jsonrpc.org/specification>. --+-- If you have monad with 'MonadIO', 'MonadThrow' and 'MonadReader' instances,+-- it can be used as base for JSON-RPC calls.+--+-- Example:+--+-- @+--   newtype MyMonad a = ...+--+--   instance JsonRpc MyMonad+--+--   foo :: Mymonad Text+--   foo = remote "foo"+-- @+--+-- Arguments of function are stored into @params@ request array.+--+-- Example:+--+-- @+--   myMethod :: JsonRpc m => Int -> Bool -> m String+--   myMethod = remote "myMethod"+-- @+-- -module Network.JsonRpc.TinyClient (-    JsonRpcException(..)-  , RpcError(..)-  , MethodName-  , ServerUri-  , Remote-  , remote-  ) where+module Network.JsonRpc.TinyClient+    (+    -- * The JSON-RPC remote call monad+      JsonRpc(..)+    , MethodName -import           Control.Applicative    ((<|>))-import           Control.Exception      (Exception)-import           Control.Monad          ((<=<))-import           Control.Monad.Catch    (MonadThrow, throwM)-import           Control.Monad.IO.Class (MonadIO, liftIO)-import           Control.Monad.Reader   (MonadReader, ask)-import           Data.Aeson-import           Data.ByteString.Lazy   (ByteString)-import           Data.Text              (Text, unpack)-import           Network.HTTP.Client    (Manager, RequestBody (RequestBodyLBS),-                                         httpLbs, method, parseRequest,-                                         requestBody, requestHeaders,-                                         responseBody)+    -- * JSON-RPC client settings+    , JsonRpcClient+    , defaultSettings+    , jsonRpcServer+    , jsonRpcManager --- | Name of called method.-type MethodName = Text+    -- * Error handling+    , JsonRpcException(..)+    , RpcError(..)+    ) where --- | JSON-RPC server URI-type ServerUri  = String+import           Control.Applicative     ((<|>))+import           Control.Exception       (Exception)+import           Control.Monad           ((<=<))+import           Control.Monad.Catch     (MonadThrow (..))+import           Control.Monad.IO.Class  (MonadIO (..))+import           Control.Monad.State     (MonadState)+import           Crypto.Number.Generate  (generateMax)+import           Data.Aeson              (FromJSON (..), ToJSON (..),+                                          Value (String), eitherDecode, encode,+                                          object, withObject, (.:), (.:?), (.=))+import           Data.ByteString.Lazy    (ByteString)+import           Data.Text               (Text, unpack)+import           Lens.Micro.Mtl          (use)+import           Lens.Micro.TH           (makeLenses)+import           Network.HTTP.Client     (Manager, RequestBody (RequestBodyLBS),+                                          httpLbs, method, newManager,+                                          parseRequest, requestBody,+                                          requestHeaders, responseBody)+import           Network.HTTP.Client.TLS (tlsManagerSettings) --- | JSON-RPC minimal client config-type Config = (ServerUri, Manager)+-- | JSON-RPC monad constrait.+type JsonRpcM m = (MonadIO m, MonadThrow m, MonadState JsonRpcClient m) +-- | JSON-RPC client state vars.+data JsonRpcClient = JsonRpcClient+    { _jsonRpcManager :: Manager    -- ^ HTTP connection manager.+    , _jsonRpcServer  :: String     -- ^ Remote server URI.+    }++$(makeLenses ''JsonRpcClient)++-- | Create default 'JsonRpcClient' settings.+defaultSettings :: MonadIO m+                => String           -- ^ JSON-RPC server URI+                -> m JsonRpcClient+defaultSettings srv = liftIO $ JsonRpcClient+  <$> newManager tlsManagerSettings+  <*> pure srv++instance Show JsonRpcClient where+    show JsonRpcClient{..} = "JsonRpcClient<" ++ _jsonRpcServer ++ ">"+ -- | JSON-RPC request.-data Request = Request { rqMethod :: !Text-                       , rqId     :: !Int-                       , rqParams :: !Value }+data Request = Request+    { rqMethod :: !Text+    , rqId     :: !Int+    , rqParams :: !Value+    } deriving (Eq, Show)  instance ToJSON Request where     toJSON rq = object [ "jsonrpc" .= String "2.0"                        , "method"  .= rqMethod rq                        , "params"  .= rqParams rq-                       , "id"      .= rqId rq ]+                       , "id"      .= rqId rq+                       ]  -- | JSON-RPC response. data Response = Response-  { rsResult :: !(Either RpcError Value)-  } deriving (Eq, Show)+    { rsResult :: !(Either RpcError Value)+    } deriving (Eq, Show)  instance FromJSON Response where     parseJSON =@@ -77,10 +133,10 @@  -- | JSON-RPC error message data RpcError = RpcError-  { errCode    :: !Int-  , errMessage :: !Text-  , errData    :: !(Maybe Value)-  } deriving Eq+    { errCode    :: !Int+    , errMessage :: !Text+    , errData    :: !(Maybe Value)+    } deriving Eq  instance Show RpcError where     show (RpcError code msg dat) =@@ -93,69 +149,51 @@                        <*> v .: "message"                        <*> v .:? "data" --- | Typeclass for JSON-RPC monad base.------ If you have monad with 'MonadIO', 'MonadThrow' and 'MonadReader' instances,--- it can be used as base for JSON-RPC calls.------ Example:------ @---   newtype MyMonad a = ...------   instance Remote MyMonad (Mymonad a)------   foo :: Int -> Bool -> Mymonad Text---   foo = remote "foo"--- @----class (MonadIO m, MonadThrow m, MonadReader Config m) => Remote m a | a -> m where-    remote_ :: ([Value] -> m ByteString) -> a+data JsonRpcException+    = ParsingException String+    | CallException RpcError+    deriving (Show, Eq) -    default remote_ :: (FromJSON b, m b ~ a) => ([Value] -> m ByteString) -> a-    remote_ f = decodeResponse =<< f []+instance Exception JsonRpcException +class JsonRpcM m => Remote m a | a -> m where+    remote' :: ([Value] -> m ByteString) -> a+ instance (ToJSON a, Remote m b) => Remote m (a -> b) where-    remote_ f x = remote_ (\xs -> f (toJSON x : xs))+    remote' f x = remote' (\xs -> f (toJSON x : xs)) --- | Remote call of JSON-RPC method.------ Arguments of function are stored into @params@ request array.------ Example:------ @---   myMethod :: Int -> Bool -> m String---   myMethod = remote "myMethod"--- @----remote :: Remote m a => MethodName -> a-{-# INLINE remote #-}-remote = remote_ . call+instance {-# INCOHERENT #-} (JsonRpcM m, FromJSON b) => Remote m (m b) where+    remote' f = decodeResponse =<< f [] -call :: (MonadIO m,-         MonadThrow m,-         MonadReader Config m)+-- | Name of called method.+type MethodName = Text++-- | JSON-RPC call monad.+class JsonRpcM m => JsonRpc m where+    -- | Remote call of JSON-RPC method.+    remote :: Remote m a => MethodName -> a+    {-# INLINE remote #-}+    remote = remote' . call++call :: JsonRpcM m      => MethodName      -> [Value]      -> m ByteString-call n = connection . encode . Request n 1 . toJSON+call m r = do+  rid <- liftIO $ generateMax maxInt+  connection . encode $ Request m (fromInteger rid) (toJSON r)   where+    maxInt = toInteger (maxBound :: Int)     connection body = do-        (uri, manager) <- ask-        request <- parseRequest uri+        serverUri <- use jsonRpcServer+        request <- parseRequest serverUri         let request' = request                      { requestBody = RequestBodyLBS body                      , requestHeaders = [("Content-Type", "application/json")]-                     , method = "POST" }+                     , method = "POST"+                     }+        manager <- use jsonRpcManager         responseBody <$> liftIO (httpLbs request' manager)--data JsonRpcException-    = ParsingException String-    | CallException RpcError-    deriving (Eq, Show)--instance Exception JsonRpcException  decodeResponse :: (MonadThrow m, FromJSON a)                => ByteString
+ stack.yaml view
@@ -0,0 +1,27 @@+# Resolver to choose a 'specific' stackage snapshot or a compiler version.+resolver: lts-12.14++# User packages to be built.+packages:+- '.'++# Extra package dependencies+extra-deps:+- secp256k1-haskell-0.1.4+- relapse-1.0.0.0+- vinyl-0.9.3++# Dependencies bounds+pvp-bounds: both++# Nix integration+nix:+    packages:+    - zlib+    - boost+    - jsoncpp+    - solc+    - solc.dev+    - secp256k1+    - haskellPackages.hlint+    - haskellPackages.stylish-haskell
− test-support/contracts/Migrations.sol
@@ -1,23 +0,0 @@-pragma solidity ^0.4.4;--contract Migrations {-  address public owner;-  uint public last_completed_migration;--  modifier restricted() {-    if (msg.sender == owner) _;-  }--  function Migrations() {-    owner = msg.sender;-  }--  function setCompleted(uint completed) restricted {-    last_completed_migration = completed;-  }--  function upgrade(address new_address) restricted {-    Migrations upgraded = Migrations(new_address);-    upgraded.setCompleted(last_completed_migration);-  }-}
− test-support/contracts/SimpleStorage.sol
@@ -1,12 +0,0 @@-pragma solidity ^0.4.15;--contract SimpleStorage {-    uint public count;-    -    event CountSet(uint _count);-    -    function setCount(uint _count) {-        count = _count;-        CountSet(_count);-    }-}
− test-support/convertAbi.sh
@@ -1,9 +0,0 @@-#!/bin/sh-set -xe-cd build/contracts/-mkdir -p abis--for file in *.json; do-  jq '.abi' < "$file" > "abis/$file"-done-
− test-support/inject-contract-addresses.sh
@@ -1,26 +0,0 @@-#!/usr/bin/env bash--set -ex--EXPORT_STORE=${EXPORT_STORE:-/tmp/detected-vars}-SEARCH_DIRECTORY=${SEARCH_DIRECTORY:-build/contracts}--function detect_contract_addresses() {-  for file in $(find $SEARCH_DIRECTORY -maxdepth 1 -type f -name '*.json'); do-    maybe_address=`jq -r .networks[].address $file | grep -v null | head -n 1`-    if [ -z "${maybe_address}" ]; then-      echo no addresses detected for $file >&2-    else-      contract_name=`echo $file | sed -e 's@'$SEARCH_DIRECTORY'/@@g' -e 's/.json//g'`-      echo found address "${maybe_address}" for "${contract_name}" >&2-      contract_var=`echo $contract_name | tr '[:lower:]' '[:upper:]'`_CONTRACT_ADDRESS-      echo the var for "${contract_name}" is "${contract_var}" >&2-      echo "export ${contract_var}=`echo ${maybe_address} | sed s/0x//`"-    fi-  done-}--detect_contract_addresses 2>/dev/null >$EXPORT_STORE--source $EXPORT_STORE-$@
− test-support/migrations/1_initial_migration.js
@@ -1,5 +0,0 @@-var Migrations = artifacts.require("./Migrations.sol");--module.exports = function(deployer) {-  deployer.deploy(Migrations);-};
− test-support/migrations/2_deploy_contracts.js
@@ -1,7 +0,0 @@-var SimpleStorage = artifacts.require("./SimpleStorage.sol");-var ComplexStorage = artifacts.require("./ComplexStorage.sol");--module.exports = function(deployer) {-  deployer.deploy(SimpleStorage);-  deployer.deploy(ComplexStorage);-};
− test-support/truffle.js
@@ -1,9 +0,0 @@-module.exports = {-  networks: {-    development: {-      host: "localhost",-      port: 8545,-      network_id: "*" // Match any network id-    }-  }-};
test/Network/Ethereum/Web3/Test/ComplexStorageSpec.hs view
@@ -1,7 +1,9 @@ {-# LANGUAGE DataKinds             #-} {-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns        #-} {-# LANGUAGE OverloadedLists       #-} {-# LANGUAGE OverloadedStrings     #-} {-# LANGUAGE QuasiQuotes           #-}@@ -25,29 +27,30 @@ module Network.Ethereum.Web3.Test.ComplexStorageSpec where  import           Control.Concurrent.Async         (wait)-import           Control.Concurrent.MVar+import           Control.Concurrent.MVar          (newEmptyMVar, putMVar,+                                                   takeMVar) import           Control.Monad.IO.Class           (liftIO)-import           Data.ByteArray                   (convert)-import           Data.ByteString                  (ByteString)-import           Data.Default-import           Data.Either                      (isRight)-import           Data.Maybe-import           Data.String                      (fromString)+import           Data.Default                     (def)++import           Network.Ethereum.Api.Types       (Filter (..))+import           Network.Ethereum.Contract        (new) import           Network.Ethereum.Contract.TH import           Network.Ethereum.Web3            hiding (convert)-import qualified Network.Ethereum.Web3.Eth        as Eth import           Network.Ethereum.Web3.Test.Utils-import           Network.Ethereum.Web3.Types      (Call (..), Filter (..))-import           System.Environment               (getEnv)-import           System.IO.Unsafe                 (unsafePerformIO)++ import           Test.Hspec -[abiFrom|test-support/build/contracts/abis/ComplexStorage.json|]+[abiFrom|test/contracts/ComplexStorage.json|] +deploy :: IO Address+deploy = do+    Just address <- web3 $ withAccount () $ withParam id $ new ComplexStorageContract+    putStrLn $ "ComplexStorage: " ++ show address+    return address+ spec :: Spec-spec = describe "Complex Storage" $ do-    it "should inject contract addresses" injectExportedEnvironmentVariables-    withPrimaryEthereumAccount `before` complexStorageSpec+spec = deploy `before` complexStorageSpec  complexStorageSpec :: SpecWith Address complexStorageSpec = do@@ -65,27 +68,25 @@             sByte2sVec = [sByte2sElem, sByte2sElem, sByte2sElem, sByte2sElem]             sByte2s = [sByte2sVec, sByte2sVec] -        it "can set the values of a ComplexStorage and validate them with an event" $ \primaryAccount -> do-            contractAddress <- Prelude.fmap fromString . liftIO $ getEnv "COMPLEXSTORAGE_CONTRACT_ADDRESS"-            let theCall = callFromTo primaryAccount contractAddress-                fltr    = (def :: Filter ValsSet) { filterAddress = Just [contractAddress] }+        it "can set the values of a ComplexStorage and validate them with an event" $ \storage -> do+            let fltr = (def :: Filter ValsSet) { filterAddress = Just [storage] }             -- kick off listening for the ValsSet event             vals <- newEmptyMVar-            fiber <- runWeb3Configured' $+            fiber <- web3 $                 event fltr $ \vs -> do                     liftIO $ putMVar vals vs                     pure TerminateEvent             -- kick off tx-            ret <- runWeb3Configured $ setValues theCall-                                                 sUint-                                                 sInt-                                                 sBool-                                                 sInt224-                                                 sBools-                                                 sInts-                                                 sString-                                                 sBytes16-                                                 sByte2s+            _ <- contract storage $ setValues+                                    sUint+                                    sInt+                                    sBool+                                    sInt224+                                    sBools+                                    sInts+                                    sString+                                    sBytes16+                                    sByte2s             -- wait for its ValsSet event             wait fiber             (ValsSet vsA vsB vsC vsD vsE vsF vsG vsH vsI) <- takeMVar vals@@ -99,33 +100,53 @@             vsH `shouldBe` sBytes16             vsI `shouldBe` sByte2s -        it "can verify that it set the values correctly" $ \primaryAccount -> do-            contractAddress <- Prelude.fmap fromString . liftIO $ getEnv "COMPLEXSTORAGE_CONTRACT_ADDRESS"-            let theCall = callFromTo primaryAccount contractAddress-                runGetterCall f = runWeb3Configured (f theCall)-            -- there really has to be a better way to do this-            uintVal'    <- runGetterCall uintVal-            intVal'     <- runGetterCall intVal-            boolVal'    <- runGetterCall boolVal-            int224Val'  <- runGetterCall int224Val-            boolsVal    <- runGetterCall $ \c -> boolVectorVal c 0-            intsVal     <- runGetterCall $ \c -> intListVal c 0-            stringVal'  <- runGetterCall stringVal-            bytes16Val' <- runGetterCall bytes16Val-            bytes2s     <- runGetterCall $ \c -> bytes2VectorListVal c 0 0+        it "can verify that it set the values correctly" $ \storage -> do+            -- Write a values+            _ <- contract storage $ setValues+                                    sUint+                                    sInt+                                    sBool+                                    sInt224+                                    sBools+                                    sInts+                                    sString+                                    sBytes16+                                    sByte2s+            -- Read a couple of values+            (uintVal', intVal', boolVal', int224Val', boolsVal, intsVal, stringVal', bytes16Val', bytes2s)+                <- contract storage $ (,,,,,,,,)+                    <$> uintVal+                    <*> intVal+                    <*> boolVal+                    <*> int224Val+                    <*> boolVectorVal 0+                    <*> intListVal 0+                    <*> stringVal+                    <*> bytes16Val+                    <*> bytes2VectorListVal 0 0+             uintVal'    `shouldBe` sUint             intVal'     `shouldBe` sInt             boolVal'    `shouldBe` sBool             int224Val'  `shouldBe` sInt224             boolsVal    `shouldBe` True-            intsVal     `shouldBe` sInts  Prelude.!! 0+            intsVal     `shouldBe` head sInts             stringVal'  `shouldBe` sString             bytes16Val' `shouldBe` sBytes16-            bytes2s `shouldBe` sByte2sElem+            bytes2s     `shouldBe` sByte2sElem -        it "can decode a complicated value correctly" $ \primaryAccount -> do-            contractAddress <- Prelude.fmap fromString . liftIO $ getEnv "COMPLEXSTORAGE_CONTRACT_ADDRESS"-            let theCall = callFromTo primaryAccount contractAddress-                runGetterCall f = runWeb3Configured (f theCall)-            allVals <- runGetterCall getVals+        it "can decode a complicated value correctly" $ \storage -> do+            -- Write a values+            _ <- contract storage $ setValues+                                    sUint+                                    sInt+                                    sBool+                                    sInt224+                                    sBools+                                    sInts+                                    sString+                                    sBytes16+                                    sByte2s+            -- Read a all values+            allVals <- contract storage getVals             allVals `shouldBe` (sUint, sInt, sBool, sInt224, sBools, sInts, sString, sBytes16, sByte2s)
+ test/Network/Ethereum/Web3/Test/ERC20Spec.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE QuasiQuotes           #-}+module Network.Ethereum.Web3.Test.ERC20Spec where++import           Test.Hspec++import           Network.Ethereum.Contract.TH (abiFrom)+import           Network.Ethereum.Web3        (Account, UIntN)+import           Network.JsonRpc.TinyClient   (JsonRpc)++[abiFrom|examples/token/ERC20.json|]++-- this spec is just to test compilation+spec :: Spec+spec = return ()++getBalance :: (JsonRpc m, Account p t, Functor (t m))+           => t m (UIntN 256)+getBalance = balanceOf "0x1234567890123456789011234567890234567890"
+ test/Network/Ethereum/Web3/Test/LinearizationSpec.hs view
@@ -0,0 +1,192 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE KindSignatures        #-}+{-# LANGUAGE LambdaCase            #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns        #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE QuasiQuotes           #-}+{-# LANGUAGE RecordWildCards       #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE TypeApplications      #-}++-- Module      :  Network.Ethereum.Web3.Test.SimpleStorage+-- Copyright   :  Alexander Krupenkin 2016+-- License     :  BSD3+--+-- Maintainer  :  mail@akru.me+-- Stability   :  experimental+-- Portability :  unportable+--+-- SimpleStorage is a Solidity contract which stores a uint256.+-- The point of this test is to test function calls to update and+-- read the value, as well as an event monitor.++module Network.Ethereum.Web3.Test.LinearizationSpec where++import           Control.Concurrent               (forkIO)+import           Control.Concurrent.Async         (forConcurrently_)+import           Control.Concurrent.MVar+import           Control.Concurrent.STM           (atomically)+import           Control.Concurrent.STM.TQueue    (TQueue, flushTQueue,+                                                   newTQueueIO, writeTQueue)+import           Control.Monad                    (void)+import           Control.Monad.IO.Class           (MonadIO (..))+import           Control.Monad.Trans.Reader       (ReaderT, ask)+import           Data.Default+import           Data.Either+import           Data.List                        (sort)+import           Data.Maybe                       (fromJust)+import           System.Random                    (randomRIO)+import           Test.Hspec++import qualified Network.Ethereum.Api.Eth         as Eth+import           Network.Ethereum.Api.Types       (Change (..), Filter (..),+                                                   TxReceipt, unQuantity)+import           Network.Ethereum.Contract        (new)+import           Network.Ethereum.Contract.Event+import           Network.Ethereum.Contract.TH     (abiFrom)+import           Network.Ethereum.Web3+import           Network.Ethereum.Web3.Test.Utils++[abiFrom|test/contracts/Linearization.json|]++deploy :: IO Address+deploy = do+    Just address <- web3 $ withAccount () $ withParam id $ new LinearizationContract+    putStrLn $ "Linearization: " ++ show address+    return address++spec :: Spec+spec = do+    deploy `before` linearizationSpec+    deploy `before` floodSpec++floodCount :: Int+floodCount = 200++linearizationSpec :: SpecWith Address+linearizationSpec =+    describe "can bundle and linearize events" $ do+        it "can call e12" $ \linearization -> do+            var <- monitorE1OrE2 linearization+            _ <- contract linearization e12+            res <- takeMVar var+            res `shouldSatisfy` isLeft++        it "can call e21" $ \linearization -> do+            -- wait on the next block+            web3 Eth.blockNumber >>= \bn -> awaitBlock (bn + 1)+            var <- monitorE1OrE2 linearization+            _ <- contract linearization e21+            res <- takeMVar var+            res `shouldSatisfy` isRight++singleFlood :: forall m. (MonadIO m) => Address -> m TxReceipt+singleFlood linearization = liftIO $ do+    rando :: Int <- randomRIO (1, 4)+    contract linearization $+        case rando of+            1 -> e1+            2 -> e2+            3 -> e3+            4 -> e4+            _ -> error "got a number outside of (1,4) after randomR (1,4)"++floodSpec :: SpecWith Address+floodSpec = describe "can correctly demonstrate the difference between `multiEvent` and multiple `event'`s" $ do+    it "properly linearizes with `multiEvent` when flooded and doesn't with multiple `event`s" $ \linearization -> do+        multiQ <- monitorAllFourMulti linearization+        parQ <- monitorAllFourPar linearization+        -- to let the filter settle so we dont block indefinitely on missing events?+        sleepBlocks 10++        -- flood em and wait for all to finish+        liftIO . forConcurrently_ [1..floodCount] . const $ singleFlood linearization++        -- to let the event listeners catch up+        sleepBlocks 10++        -- wait for all multiEvents to be received and flush em out+        multiReceivedEvents <- liftIO . atomically $ flushTQueue multiQ+        parReceivedEvents <- liftIO . atomically $ flushTQueue parQ++        -- did we get at least 1/4 of the events? (this is a gotcha when flooding, sometimes nonces get repeated)+        length multiReceivedEvents `shouldSatisfy` (>= (floodCount `div` 4))+        length parReceivedEvents `shouldSatisfy` (>= (floodCount `div` 4))++        -- did both listeners see the same amount of events?+        length multiReceivedEvents `shouldBe` length parReceivedEvents++        -- the events pushed into the multi TQueue should already be sorted if they happened in the right order+        sort multiReceivedEvents `shouldBe` multiReceivedEvents+        -- the events pushed into the TQueue should not be sorted if they didnt come in in the right order+        sort parReceivedEvents `shouldNotBe` parReceivedEvents++monitorE1OrE2 :: Address -> IO (MVar (Either E1 E2))+monitorE1OrE2 addr = do+    var <- newEmptyMVar+    let fltr1 = (def :: Filter E1) { filterAddress = Just [addr] }+        fltr2 = (def :: Filter E2) { filterAddress = Just [addr] }+        filters = fltr1 :? fltr2 :? NilFilters+        handler1 ev1 = do+            liftIO $ putMVar var (Left ev1)+            return TerminateEvent+        handler2 ev2 = do+            liftIO $ putMVar var (Right ev2)+            return TerminateEvent+        handlers = H handler1 :& H handler2 :& RNil+    _ <- web3 $ multiEvent filters handlers+    return var++data EventTag = ETE1 | ETE2 | ETE3 | ETE4+    deriving (Eq, Read, Show)++instance {-# OVERLAPPING #-} Ord (EventTag, Integer, Integer) where+    (_, b1, t1) `compare` (_, b2, t2) =+        let bCmp = b1 `compare` b2+        in if bCmp == EQ then t1 `compare` t2+                         else bCmp++monitorAllFourMulti :: Address+                    -> IO (TQueue (EventTag, Integer, Integer))+monitorAllFourMulti addr = do+    q <- newTQueueIO+    let f :: forall a. Default (Filter a) => Filter a+        f = defFilter addr+        h = enqueueingHandler q+        filters = f @E1 :? f @E2 :? f @E3 :? f @E4 :? NilFilters+        handlers = h ETE1 :& h ETE2 :& h ETE3 :& h ETE4 :& RNil+    void . web3 $ multiEvent filters handlers+    return q++monitorAllFourPar :: Address+                  -> IO (TQueue (EventTag, Integer, Integer))+monitorAllFourPar addr = do+    q <- newTQueueIO+    let f :: forall a. Default (Filter a) => Filter a+        f = defFilter addr+        h = enqueueingHandler q+        unH (H h) = h++    void . forkIO . web3 $ event' (f @E1) (unH $ h ETE1)+    void . forkIO . web3 $ event' (f @E2) (unH $ h ETE2)+    void . forkIO . web3 $ event' (f @E3) (unH $ h ETE3)+    void . forkIO . web3 $ event' (f @E4) (unH $ h ETE4)+    return q++defFilter :: forall a. Default (Filter a) => Address -> Filter a+defFilter addr = (def :: Filter a) { filterAddress = Just [addr] }++enqueueingHandler :: forall a. TQueue (EventTag, Integer, Integer)+                  -> EventTag+                  -> Handler (ReaderT Change Web3 EventAction) a+enqueueingHandler q tag = H . const $ do+    Change{..} <- ask+    let bn = unQuantity $ fromJust changeBlockNumber+        li = unQuantity $ fromJust changeLogIndex+    liftIO . atomically $ writeTQueue q (tag, bn, li)+    return ContinueEvent
+ test/Network/Ethereum/Web3/Test/RegistrySpec.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedLists       #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE QuasiQuotes           #-}+{-# LANGUAGE TemplateHaskell       #-}++module Network.Ethereum.Web3.Test.RegistrySpec where++import           Data.Default                 (def)+import           Test.Hspec                   (Spec)++import           Network.Ethereum.Api.Types   (Filter)+import           Network.Ethereum.Contract.TH (abiFrom)+import           Network.Ethereum.Web3        (EventAction (TerminateEvent),+                                               Web3, event)++[abiFrom|test/contracts/Registry.json|]++-- this spec is just to test compilation+spec :: Spec+spec = return ()++monitor :: Web3 ()+monitor = do+  let fltr1 = def :: Filter A+      fltr2 = def :: Filter B+  event fltr1 $ \_ -> pure TerminateEvent+  event fltr2 $ \_ -> pure TerminateEvent+  pure ()
test/Network/Ethereum/Web3/Test/SimpleStorageSpec.hs view
@@ -1,9 +1,11 @@ {-# LANGUAGE DataKinds             #-} {-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE KindSignatures        #-} {-# LANGUAGE LambdaCase            #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns        #-} {-# LANGUAGE OverloadedStrings     #-} {-# LANGUAGE QuasiQuotes           #-} {-# LANGUAGE ScopedTypeVariables   #-}@@ -20,172 +22,157 @@ -- SimpleStorage is a Solidity contract which stores a uint256. -- The point of this test is to test function calls to update and -- read the value, as well as an event monitor.+--  module Network.Ethereum.Web3.Test.SimpleStorageSpec where -import           Control.Concurrent               (threadDelay) import           Control.Concurrent.Async         (wait) import           Control.Concurrent.MVar-import           Control.Monad                    (void) import           Control.Monad.IO.Class           (liftIO) import           Control.Monad.Trans.Class        (lift) import           Control.Monad.Trans.Reader       (ask)-import           Data.ByteString                  (ByteString)-import           Data.Default-import           Data.Either                      (isRight)-import           Data.Foldable                    (forM_)+import           Data.Default                     (def) import           Data.List                        (sort)-import           Data.Maybe-import           Data.Monoid-import           Data.String                      (fromString)-import qualified Data.Text                        as T-import           Data.Traversable                 (for)-import           GHC.TypeLits+import           Data.Monoid                      ((<>))+import           Test.Hspec +import qualified Network.Ethereum.Api.Eth         as Eth+import           Network.Ethereum.Api.Provider    (forkWeb3)+import           Network.Ethereum.Api.Types+import           Network.Ethereum.Contract        (new)+import           Network.Ethereum.Contract.Event  (event') import           Network.Ethereum.Contract.TH-import           Network.Ethereum.Web3            hiding (convert)-import qualified Network.Ethereum.Web3.Eth        as Eth-import           Network.Ethereum.Web3.Provider   (forkWeb3)-import           Network.Ethereum.Web3.Types+import           Network.Ethereum.Web3 -import           Numeric                          (showHex)-import           System.Environment               (getEnv)-import           System.IO.Unsafe                 (unsafePerformIO)-import           Test.Hspec  import           Network.Ethereum.Web3.Test.Utils -[abiFrom|test-support/build/contracts/abis/SimpleStorage.json|]+[abiFrom|test/contracts/SimpleStorage.json|] -unCountSet :: CountSet -> UIntN 256-unCountSet (CountSet n) = n+unEvT_CountSet :: EvT_CountSet -> UIntN 256+unEvT_CountSet (EvT_CountSet n) = n -contractAddress :: Address-contractAddress = fromString . unsafePerformIO $ getEnv "SIMPLESTORAGE_CONTRACT_ADDRESS"+deploy :: IO Address+deploy = do+    Just address <- web3 $ withAccount () $ withParam id $ new SimpleStorageContract+    putStrLn $ "SimpleStorage: " ++ show address+    return address  spec :: Spec-spec = describe "Simple Storage" $ do-    it "should inject contract addresses" injectExportedEnvironmentVariables-    withPrimaryEthereumAccount `before` interactions-    withPrimaryEthereumAccount `before` events+spec = deploy `before` do+  interactions+  events  interactions :: SpecWith Address interactions = describe "can interact with a SimpleStorage contract" $ do     -- todo: this should ideally be arbitrary!     let theValue = 12345-    it "can set the value of a SimpleStorage contract" $ \primaryAccount -> do-        let theCall = callFromTo primaryAccount contractAddress-        ret <- runWeb3Configured $ setCount theCall theValue-        True `shouldBe` True -- we need to get this far -    it "can read the value back" $ \primaryAccount -> do-        let theCall = callFromTo primaryAccount contractAddress-        now <- runWeb3Configured Eth.blockNumber+    it "can set the value of a SimpleStorage contract and read the value back" $ \storage -> do+        _ <- contract storage $ setCount theValue++        now <- web3 Eth.blockNumber         let later = now + 3         awaitBlock later-        v <- runWeb3Configured (count theCall)++        v <- contract storage count         v `shouldBe` theValue  events :: SpecWith Address-events = describe "can interact with a SimpleStorage contract across block intervals" $ do-    it "can stream events starting and ending in the future, unbounded" $ \primaryAccount -> do-        var <- newMVar []-        let theCall = callFromTo primaryAccount contractAddress-            theSets = [1, 2, 3]-        print "Setting up the filter..."-        fiber <- runWeb3Configured' $ do-          let fltr = (def :: Filter CountSet) { filterAddress = Just [contractAddress] }-          forkWeb3 $ processUntil' var fltr ((3 ==) . length)-        print "Setting the values..."-        setValues theCall theSets-        wait fiber-        print "Filter caught 3 values..."-        vals <- takeMVar var-        sort (unCountSet <$> vals) `shouldBe` sort theSets+events = do+    describe "can interact with a SimpleStorage contract across block intervals" $ do+        it "can stream events starting and ending in the future, unbounded" $ \storage -> do+            var <- newMVar []+            let theSets = [1, 2, 3]+            putStrLn "Setting up the filter..."+            fiber <- web3 $ do+                let fltr = (def :: Filter EvT_CountSet) { filterAddress = Just [storage] }+                forkWeb3 $ processUntil' var fltr ((3 ==) . length)+            putStrLn "Setting the values..."+            setValues storage theSets+            wait fiber+            putStrLn "Filter caught 3 values..."+            vals <- takeMVar var+            sort (unEvT_CountSet <$> vals) `shouldBe` sort theSets -    it "can stream events starting and ending in the future, bounded" $ \primaryAccount -> do-        runWeb3Configured Eth.blockNumber >>= \bn -> awaitBlock (bn + 1)-        var <- newMVar []-        let theCall = callFromTo primaryAccount contractAddress-            theSets = [13, 14, 15]-        start <- runWeb3Configured Eth.blockNumber-        let later = BlockWithNumber (start + 3)-            latest = BlockWithNumber (start + 8)-            fltr = (def :: Filter CountSet) { filterAddress = Just [contractAddress]-                                            , filterFromBlock = later-                                            , filterToBlock = latest }-        print "Setting up the filter..."-        fiber <- runWeb3Configured' $-          forkWeb3 $ processUntil' var fltr ((3 ==) . length)-        awaitBlock (start + 3)-        print "Setting the values..."-        setValues theCall theSets-        wait fiber-        print "Filter caught 3 values..."-        vals <- takeMVar var-        sort (unCountSet <$> vals) `shouldBe` sort theSets+        it "can stream events starting and ending in the future, bounded" $ \storage -> do+            var <- newMVar []+            let theSets = [13, 14, 15]+            start <- web3 Eth.blockNumber+            let later = BlockWithNumber (start + 3)+                latest = BlockWithNumber (start + 8)+                fltr = (def :: Filter EvT_CountSet) { filterAddress = Just [storage]+                                                    , filterFromBlock = later+                                                    , filterToBlock = latest+                                                    }+            putStrLn "Setting up the filter..."+            fiber <- web3 $+                forkWeb3 $ processUntil' var fltr ((3 ==) . length)+            awaitBlock (start + 3)+            putStrLn "Setting the values..."+            setValues storage theSets+            wait fiber+            putStrLn "Filter caught 3 values..."+            vals <- takeMVar var+            sort (unEvT_CountSet <$> vals) `shouldBe` init (sort theSets) -    it "can stream events starting in the past and ending in the future" $ \primaryAccount -> do-        runWeb3Configured Eth.blockNumber >>= \bn -> awaitBlock (bn + 1)-        var <- newMVar []-        blockNumberVar <- newEmptyMVar-        let theCall = callFromTo primaryAccount contractAddress-            theSets1 = [7, 8, 9]-            theSets2 = [10, 11, 12]-        start <- runWeb3Configured Eth.blockNumber-        let fltr = (def :: Filter CountSet) { filterAddress = Just [contractAddress] }-        fiber <- runWeb3Configured' $ do-          forkWeb3 $ processUntil var fltr ((3 ==) . length) (liftIO . putMVar blockNumberVar . changeBlockNumber)-        print "Running first transactions as past transactions..."-        setValues theCall theSets1-        wait fiber-        print "All past transactions succeeded... "-        Just end <- takeMVar blockNumberVar-        awaitBlock $ end + 1 -- make past transactions definitively in past-        var' <- newMVar []-        fiber <- runWeb3Configured' $ do-          let fltr = (def :: Filter CountSet) { filterAddress = Just [contractAddress]-                                              , filterFromBlock = BlockWithNumber start}-          forkWeb3 $ processUntil' var' fltr ((6 ==) . length)-        print "Setting more values"-        setValues theCall theSets2-        wait fiber-        print "All new values have ben set"-        vals <- takeMVar var'-        sort (unCountSet <$> vals) `shouldBe` sort (theSets1 <> theSets2)+        it "can stream events starting in the past and ending in the future" $ \storage -> do+            var <- newMVar []+            blockNumberVar <- newEmptyMVar+            let theSets1 = [7, 8, 9]+                theSets2 = [10, 11, 12]+            start <- web3 Eth.blockNumber+            let fltr = (def :: Filter EvT_CountSet) { filterAddress = Just [storage] }+            fiber <- web3 $ do+                forkWeb3 $ processUntil var fltr ((3 ==) . length) (liftIO . putMVar blockNumberVar . changeBlockNumber)+            putStrLn "Running first transactions as past transactions..."+            setValues storage theSets1+            wait fiber+            putStrLn "All past transactions succeeded... "+            Just end <- takeMVar blockNumberVar+            awaitBlock $ end + 1  -- make past transactions definitively in past+            var' <- newMVar []+            fiber' <- web3 $ do+                let fltr' = (def :: Filter EvT_CountSet) { filterAddress = Just [storage]+                                                        , filterFromBlock = BlockWithNumber start}+                forkWeb3 $ processUntil' var' fltr' ((6 ==) . length)+            putStrLn "Setting more values"+            setValues storage theSets2+            wait fiber'+            putStrLn "All new values have ben set"+            vals <- takeMVar var'+            sort (unEvT_CountSet <$> vals) `shouldBe` sort (theSets1 <> theSets2) -    it "can stream events starting and ending in the past, bounded" $ \primaryAccount -> do-        runWeb3Configured Eth.blockNumber >>= \bn -> awaitBlock (bn + 1)+    it "can stream events starting and ending in the past, bounded" $ \storage -> do         var <- newMVar []-        let theCall = callFromTo primaryAccount contractAddress-            theSets = [4, 5, 6]-        start <- runWeb3Configured Eth.blockNumber+        let theSets = [4, 5, 6]+        start <- web3 Eth.blockNumber         blockNumberVar <- newEmptyMVar-        let fltr = (def :: Filter CountSet) { filterAddress = Just [contractAddress] }-        print "Setting up filter for past transactions..."-        fiber <- runWeb3Configured' $ do+        let fltr = (def :: Filter EvT_CountSet) { filterAddress = Just [storage] }+        putStrLn "Setting up filter for past transactions..."+        fiber <- web3 $ do           forkWeb3 $ processUntil var fltr ((3 ==) . length) (liftIO . putMVar blockNumberVar . changeBlockNumber)-        print "Setting values"-        setValues theCall theSets+        putStrLn "Setting values"+        setValues storage theSets         wait fiber-        print "All values have been set"+        putStrLn "All values have been set"         Just end <- takeMVar blockNumberVar         var' <- newMVar []         let fltr' = fltr { filterFromBlock = BlockWithNumber start                          , filterToBlock = BlockWithNumber end                          }         awaitBlock $ end + 1  -- make it definitively in the past-        runWeb3Configured $ processUntil' var' fltr' ((3 ==) . length)+        web3 $ processUntil' var' fltr' ((3 ==) . length)         vals <- takeMVar var'-        sort (unCountSet <$> vals) `shouldBe` sort theSets+        sort (unEvT_CountSet <$> vals) `shouldBe` sort theSets -processUntil :: MVar [CountSet]-             -> Filter CountSet-             -> ([CountSet] -> Bool)  -- TODO: make it work for any event+processUntil :: MVar [EvT_CountSet]+             -> Filter EvT_CountSet+             -> ([EvT_CountSet] -> Bool)  -- TODO: make it work for any event              -> (Change -> Web3 ())              -> Web3 ()-processUntil var filter predicate action = do-  event' filter $ \(ev :: CountSet) -> do+processUntil var fltr predicate action = do+  event' fltr $ \(ev :: EvT_CountSet) -> do     newV <- liftIO $ modifyMVar var $ \v -> return (ev:v, ev:v)     if predicate newV         then do@@ -194,13 +181,11 @@           return TerminateEvent         else return ContinueEvent -processUntil' :: MVar [CountSet]-              -> Filter CountSet-              -> ([CountSet] -> Bool)+processUntil' :: MVar [EvT_CountSet]+              -> Filter EvT_CountSet+              -> ([EvT_CountSet] -> Bool)               -> Web3 ()-processUntil' var filter predicate = processUntil var filter predicate (const $ return ())+processUntil' var fltr predicate = processUntil var fltr predicate (const $ return ()) -setValues :: Call -> [UIntN 256] -> IO ()-setValues theCall theSets = forM_ theSets $ \v -> do-  runWeb3Configured (setCount theCall v)-  threadDelay 1000000+setValues :: Address -> [UIntN 256] -> IO ()+setValues storage = mapM_ (contract storage . setCount)
test/Network/Ethereum/Web3/Test/Utils.hs view
@@ -1,92 +1,66 @@-{-# LANGUAGE LambdaCase #-}-module Network.Ethereum.Web3.Test.Utils-  ( injectExportedEnvironmentVariables-  , runWeb3Configured-  , runWeb3Configured'-  , withAccounts-  , withPrimaryEthereumAccount-  , callFromTo-  , sleepSeconds-  , microtime-  , awaitBlock-  ) where--import           Control.Concurrent                (MVar, threadDelay,-                                                    tryTakeMVar)-import           Control.Monad.IO.Class            (liftIO)-import           Data.Default-import           Data.Either                       (isRight)-import           Data.List.Split                   (splitOn)-import           Data.Maybe                        (fromMaybe)-import           Data.Ratio                        (numerator)-import           Data.String                       (IsString, fromString)-import qualified Data.Text                         as T-import           Data.Time.Clock.POSIX             (getPOSIXTime)-import           Data.Traversable                  (for)+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-} -import           Network.Ethereum.ABI.Prim.Address (Address)-import           Network.Ethereum.Web3.Eth         (accounts, blockNumber)-import           Network.Ethereum.Web3.Provider    (Provider (..), Web3,-                                                    Web3Error, runWeb3')-import           Network.Ethereum.Web3.Types       (Call (..), Quantity)-import           System.Environment                (lookupEnv, setEnv)-import           Test.Hspec.Expectations           (shouldSatisfy)+module Network.Ethereum.Web3.Test.Utils where -rpcUri :: IO String-rpcUri =  liftIO (fromMaybe "http://localhost:8545" <$> lookupEnv "WEB3_PROVIDER")+import           Control.Concurrent            (threadDelay)+import           Control.Exception             (SomeException, catch)+import           Control.Monad.IO.Class        (liftIO)+import           Data.Maybe                    (fromMaybe)+import           Data.Ratio                    (numerator)+import           Data.Time.Clock.POSIX         (getPOSIXTime)+import           Lens.Micro                    ((.~))+import           Network.HTTP.Client           (Manager, defaultManagerSettings,+                                                managerConnCount,+                                                managerRawConnection,+                                                managerRetryableException,+                                                newManager)+import           System.Environment            (lookupEnv)+import           System.IO.Unsafe              (unsafePerformIO) -exportStore :: String-exportStore = "./test-support/.detected-contract-addresses"+import           Data.Solidity.Prim.Address    (Address)+import           Network.Ethereum.Account      (DefaultAccount, to, withAccount,+                                                withParam)+import           Network.Ethereum.Api.Eth      (accounts, blockNumber)+import           Network.Ethereum.Api.Provider (Provider (..), Web3,+                                                runWeb3With)+import           Network.Ethereum.Api.Types    (Quantity) -loadExportedEnvironmentVariables :: IO [(String, String)]-loadExportedEnvironmentVariables = do-    exportables <- lines <$> readFile exportStore-    detecteds <- for exportables $ \line -> case words line of-        ["export", e] -> case splitOn "=" e of-            [x]    -> detectedEnv x ""-            [k, v] -> detectedEnv k v-            _      -> warnMalformation $ "oddly structured export statement " ++ line-        _ -> warnMalformation $ "no export in line " ++ line-    return $ concat detecteds+-- shared manager used throughout the helpers here to prevent hammering geth from ruining everything+-- this also retrys on ALL exceptions, including ConnectionResetByPeer and stuff like that+sharedManager :: Manager+sharedManager = unsafePerformIO $ newManager defaultManagerSettings+    { managerConnCount = 5+    , managerRetryableException = const False+    , managerRawConnection = fixRawConnection retryOpenConnection+    } -    where warnMalformation m = do-            putStrLn $ m ++ ". are you sure you're using the right inject-contract-addresses.sh?"-            pure []-          detectedEnv k v = do-              -- putStrLn $ "detected " ++ k ++ "=" ++ v-              pure [(k, v)]+    where retryOpenConnection = threadDelay 500000 >> managerRawConnection defaultManagerSettings+          fixRawConnection f = f `catch` (\(_ :: SomeException) -> fixRawConnection f)+{-# NOINLINE sharedManager #-} -injectExportedEnvironmentVariables :: IO ()-injectExportedEnvironmentVariables = do-    detectedEnvs <- loadExportedEnvironmentVariables-    sequence_ (uncurry setEnv <$> detectedEnvs)+rpcUri :: IO String+rpcUri = liftIO (fromMaybe "http://localhost:8545" <$> lookupEnv "WEB3_PROVIDER") -runWeb3Configured :: Show a => Web3 a -> IO a-runWeb3Configured f = do-    provider <- HttpProvider <$> rpcUri-    v <- runWeb3' provider f-    v `shouldSatisfy` isRight-    let Right a = v in return a+contract :: Address+         -> DefaultAccount Web3 a+         -> IO a+contract a = web3 . withAccount () . withParam (to .~ a) -runWeb3Configured' :: Web3 a -> IO a-runWeb3Configured' f = do+web3 :: Web3 a -> IO a+web3 ma = do     provider <- HttpProvider <$> rpcUri-    Right v <- runWeb3' provider f-    return v+    v <- runWeb3With sharedManager provider ma+    case v of+        Left e   -> print e >> threadDelay 1000000 >> web3 ma+        Right v' -> return v'  withAccounts :: ([Address] -> IO a) -> IO a-withAccounts f = runWeb3Configured accounts >>= f+withAccounts f = web3 accounts >>= f  withPrimaryEthereumAccount :: IO Address withPrimaryEthereumAccount = withAccounts (pure . head) -callFromTo :: Address -> Address -> Call-callFromTo from to =-    def { callFrom = Just from-        , callTo   = Just to-        , callGasPrice = Just 4000000000-        }- sleepSeconds :: Int -> IO () sleepSeconds = threadDelay . (* 1000000) @@ -95,8 +69,13 @@  awaitBlock :: Quantity -> IO () awaitBlock bn = do-    bn' <- runWeb3Configured blockNumber-    putStrLn $ "awaiting block " ++ show bn ++ ", currently " ++ show bn'+    bn' <- web3 blockNumber+    -- putStrLn $ "awaiting block " ++ show bn ++ ", currently " ++ show bn'     if bn' >= bn         then return ()         else threadDelay 1000000 >> awaitBlock bn++sleepBlocks :: Int -> IO ()+sleepBlocks n = do+    now <- web3 blockNumber+    awaitBlock $ now + fromIntegral n
+ test/contracts/ComplexStorage.json view
@@ -0,0 +1,4533 @@+{+  "contractName": "ComplexStorage",+  "abi": [+    {+      "constant": true,+      "inputs": [],+      "name": "boolVal",+      "outputs": [+        {+          "name": "",+          "type": "bool"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [],+      "name": "stringVal",+      "outputs": [+        {+          "name": "",+          "type": "string"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [],+      "name": "intVal",+      "outputs": [+        {+          "name": "",+          "type": "int256"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [+        {+          "name": "",+          "type": "uint256"+        }+      ],+      "name": "intListVal",+      "outputs": [+        {+          "name": "",+          "type": "int256"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [],+      "name": "uintVal",+      "outputs": [+        {+          "name": "",+          "type": "uint256"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [],+      "name": "int224Val",+      "outputs": [+        {+          "name": "",+          "type": "int224"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [],+      "name": "bytes16Val",+      "outputs": [+        {+          "name": "",+          "type": "bytes16"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [+        {+          "name": "",+          "type": "uint256"+        }+      ],+      "name": "boolVectorVal",+      "outputs": [+        {+          "name": "",+          "type": "bool"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [+        {+          "name": "",+          "type": "uint256"+        },+        {+          "name": "",+          "type": "uint256"+        }+      ],+      "name": "bytes2VectorListVal",+      "outputs": [+        {+          "name": "",+          "type": "bytes2"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": false,+          "name": "a",+          "type": "uint256"+        },+        {+          "indexed": false,+          "name": "b",+          "type": "int256"+        },+        {+          "indexed": false,+          "name": "c",+          "type": "bool"+        },+        {+          "indexed": false,+          "name": "d",+          "type": "int224"+        },+        {+          "indexed": false,+          "name": "e",+          "type": "bool[2]"+        },+        {+          "indexed": false,+          "name": "f",+          "type": "int256[]"+        },+        {+          "indexed": false,+          "name": "g",+          "type": "string"+        },+        {+          "indexed": false,+          "name": "h",+          "type": "bytes16"+        },+        {+          "indexed": false,+          "name": "i",+          "type": "bytes2[4][]"+        }+      ],+      "name": "ValsSet",+      "type": "event"+    },+    {+      "constant": false,+      "inputs": [+        {+          "name": "_uintVal",+          "type": "uint256"+        },+        {+          "name": "_intVal",+          "type": "int256"+        },+        {+          "name": "_boolVal",+          "type": "bool"+        },+        {+          "name": "_int224Val",+          "type": "int224"+        },+        {+          "name": "_boolVectorVal",+          "type": "bool[2]"+        },+        {+          "name": "_intListVal",+          "type": "int256[]"+        },+        {+          "name": "_stringVal",+          "type": "string"+        },+        {+          "name": "_bytes16Val",+          "type": "bytes16"+        },+        {+          "name": "_bytes2VectorListVal",+          "type": "bytes2[4][]"+        }+      ],+      "name": "setValues",+      "outputs": [],+      "payable": false,+      "stateMutability": "nonpayable",+      "type": "function"+    },+    {+      "constant": true,+      "inputs": [],+      "name": "getVals",+      "outputs": [+        {+          "name": "",+          "type": "uint256"+        },+        {+          "name": "",+          "type": "int256"+        },+        {+          "name": "",+          "type": "bool"+        },+        {+          "name": "",+          "type": "int224"+        },+        {+          "name": "",+          "type": "bool[2]"+        },+        {+          "name": "",+          "type": "int256[]"+        },+        {+          "name": "",+          "type": "string"+        },+        {+          "name": "",+          "type": "bytes16"+        },+        {+          "name": "",+          "type": "bytes2[4][]"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    }+  ],+  "bytecode": "0x608060405234801561001057600080fd5b506111be806100206000396000f3006080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631aadfbdb146100b45780632316afea14610258578063579c738a14610287578063614ac7911461031757806382a35c77146104dc5780638ba27dca146105075780639a0283ed146105485780639d49a304146105735780639eb7a6b2146105a4578063c84a4100146105f5578063f4f67ad71461063a575b600080fd5b3480156100c057600080fd5b5061025660048036038101908080359060200190929190803590602001909291908035151590602001909291908035601b0b9060200190929190806040019060028060200260405190810160405280929190826002602002808284378201915050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356fffffffffffffffffffffffffffffffff1916906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156102445784848390506080020160048060200260405190810160405280929190826004602002808284378201915050505050815260200190600101906101ff565b505050505091929192905050506106c7565b005b34801561026457600080fd5b5061026d6109b9565b604051808215151515815260200191505060405180910390f35b34801561029357600080fd5b5061029c6109cc565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102dc5780820151818401526020810190506102c1565b50505050905090810190601f1680156103095780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561032357600080fd5b5061032c610a6a565b604051808a81526020018981526020018815151515815260200187601b0b601b0b815260200186600260200280838360005b8381101561037957808201518184015260208101905061035e565b505050509050018060200180602001856fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260200180602001848103845288818151815260200191508051906020019060200280838360005b838110156103f35780820151818401526020810190506103d8565b50505050905001848103835287818151815260200191508051906020019080838360005b83811015610432578082015181840152602081019050610417565b50505050905090810190601f16801561045f5780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080516000925b818410156104c157828490602001906020020151600460200280838360005b838110156104b0578082015181840152602081019050610495565b505050509050019260010192610476565b925050509c5050505050505050505050505060405180910390f35b3480156104e857600080fd5b506104f1610d24565b6040518082815260200191505060405180910390f35b34801561051357600080fd5b5061053260048036038101908080359060200190929190505050610d2a565b6040518082815260200191505060405180910390f35b34801561055457600080fd5b5061055d610d4d565b6040518082815260200191505060405180910390f35b34801561057f57600080fd5b50610588610d53565b6040518082601b0b601b0b815260200191505060405180910390f35b3480156105b057600080fd5b506105b9610d66565b60405180826fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b34801561060157600080fd5b5061062060048036038101908080359060200190929190505050610d89565b604051808215151515815260200191505060405180910390f35b34801561064657600080fd5b5061066f6004803603810190808035906020019092919080359060200190929190505050610db2565b60405180827dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b886000819055508760018190555086600260006101000a81548160ff02191690831515021790555085600260016101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff0219169083601b0b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550846003906002610754929190610e16565b50836004908051906020019061076b929190610eaf565b508260059080519060200190610782929190610efc565b5081600660006101000a8154816fffffffffffffffffffffffffffffffff02191690837001000000000000000000000000000000009004021790555080600790805190602001906107d4929190610f7c565b507f88d23351ad32a937b11ca10530404f8297d29803e94709336b48c1f82c15b3cc898989898989898989604051808a81526020018981526020018815151515815260200187601b0b601b0b815260200186600260200280838360005b8381101561084c578082015181840152602081019050610831565b505050509050018060200180602001856fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260200180602001848103845288818151815260200191508051906020019060200280838360005b838110156108c65780820151818401526020810190506108ab565b50505050905001848103835287818151815260200191508051906020019080838360005b838110156109055780820151818401526020810190506108ea565b50505050905090810190601f1680156109325780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080516000925b8184101561099457828490602001906020020151600460200280838360005b83811015610983578082015181840152602081019050610968565b505050509050019260010192610949565b925050509c5050505050505050505050505060405180910390a1505050505050505050565b600260009054906101000a900460ff1681565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a625780601f10610a3757610100808354040283529160200191610a62565b820191906000526020600020905b815481529060010190602001808311610a4557829003601f168201915b505050505081565b600080600080610a78610fd7565b60608060006060600054600154600260009054906101000a900460ff16600260019054906101000a9004601b0b600360046005600660009054906101000a900470010000000000000000000000000000000002600784600280602002604051908101604052809291908260028015610b2a576020028201916000905b82829054906101000a900460ff16151581526020019060010190602082600001049283019260010382029150808411610af45790505b5050505050945083805480602002602001604051908101604052809291908181526020018280548015610b7c57602002820191906000526020600020905b815481526020019060010190808311610b68575b50505050509350828054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c185780601f10610bed57610100808354040283529160200191610c18565b820191906000526020600020905b815481529060010190602001808311610bfb57829003601f168201915b5050505050925080805480602002602001604051908101604052809291908181526020016000905b82821015610d0157838290600052602060002001600480602002604051908101604052809291908260048015610ced576020028201916000905b82829054906101000a90047e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060020190602082600101049283019260010382029150808411610c7a5790505b505050505081526020019060010190610c40565b505050509050985098509850985098509850985098509850909192939495969798565b60015481565b600481815481101515610d3957fe5b906000526020600020016000915090505481565b60005481565b600260019054906101000a9004601b0b81565b600660009054906101000a90047001000000000000000000000000000000000281565b600381600281101515610d9857fe5b60209182820401919006915054906101000a900460ff1681565b600782815481101515610dc157fe5b9060005260206000200181600481101515610dd857fe5b60109182820401919006600202915091509054906101000a90047e010000000000000000000000000000000000000000000000000000000000000281565b826002601f01602090048101928215610e9e5791602002820160005b83821115610e6f57835183826101000a81548160ff0219169083151502179055509260200192600101602081600001049283019260010302610e32565b8015610e9c5782816101000a81549060ff0219169055600101602081600001049283019260010302610e6f565b505b509050610eab9190610ff9565b5090565b828054828255906000526020600020908101928215610eeb579160200282015b82811115610eea578251825591602001919060010190610ecf565b5b509050610ef89190611029565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610f3d57805160ff1916838001178555610f6b565b82800160010185558215610f6b579182015b82811115610f6a578251825591602001919060010190610f4f565b5b509050610f78919061104e565b5090565b828054828255906000526020600020908101928215610fc6579160200282015b82811115610fc557825182906004610fb5929190611073565b5091602001919060010190610f9c565b5b509050610fd3919061112e565b5090565b6040805190810160405280600290602082028038833980820191505090505090565b61102691905b8082111561102257600081816101000a81549060ff021916905550600101610fff565b5090565b90565b61104b91905b8082111561104757600081600090555060010161102f565b5090565b90565b61107091905b8082111561106c576000816000905550600101611054565b5090565b90565b826004600f0160109004810192821561111d5791602002820160005b838211156110ed57835183826101000a81548161ffff02191690837e0100000000000000000000000000000000000000000000000000000000000090040217905550926020019260020160208160010104928301926001030261108f565b801561111b5782816101000a81549061ffff02191690556002016020816001010492830192600103026110ed565b505b50905061112a919061115a565b5090565b61115791905b80821115611153576000818161114a919061118b565b50600101611134565b5090565b90565b61118891905b8082111561118457600081816101000a81549061ffff021916905550600101611160565b5090565b90565b50600090555600a165627a7a7230582011b9a8b2fe6341272836fb36535a5f03b46544a58a14b17b7d49405a8247b7d10029",+  "deployedBytecode": "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631aadfbdb146100b45780632316afea14610258578063579c738a14610287578063614ac7911461031757806382a35c77146104dc5780638ba27dca146105075780639a0283ed146105485780639d49a304146105735780639eb7a6b2146105a4578063c84a4100146105f5578063f4f67ad71461063a575b600080fd5b3480156100c057600080fd5b5061025660048036038101908080359060200190929190803590602001909291908035151590602001909291908035601b0b9060200190929190806040019060028060200260405190810160405280929190826002602002808284378201915050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080356fffffffffffffffffffffffffffffffff1916906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020016000905b828210156102445784848390506080020160048060200260405190810160405280929190826004602002808284378201915050505050815260200190600101906101ff565b505050505091929192905050506106c7565b005b34801561026457600080fd5b5061026d6109b9565b604051808215151515815260200191505060405180910390f35b34801561029357600080fd5b5061029c6109cc565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102dc5780820151818401526020810190506102c1565b50505050905090810190601f1680156103095780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561032357600080fd5b5061032c610a6a565b604051808a81526020018981526020018815151515815260200187601b0b601b0b815260200186600260200280838360005b8381101561037957808201518184015260208101905061035e565b505050509050018060200180602001856fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260200180602001848103845288818151815260200191508051906020019060200280838360005b838110156103f35780820151818401526020810190506103d8565b50505050905001848103835287818151815260200191508051906020019080838360005b83811015610432578082015181840152602081019050610417565b50505050905090810190601f16801561045f5780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080516000925b818410156104c157828490602001906020020151600460200280838360005b838110156104b0578082015181840152602081019050610495565b505050509050019260010192610476565b925050509c5050505050505050505050505060405180910390f35b3480156104e857600080fd5b506104f1610d24565b6040518082815260200191505060405180910390f35b34801561051357600080fd5b5061053260048036038101908080359060200190929190505050610d2a565b6040518082815260200191505060405180910390f35b34801561055457600080fd5b5061055d610d4d565b6040518082815260200191505060405180910390f35b34801561057f57600080fd5b50610588610d53565b6040518082601b0b601b0b815260200191505060405180910390f35b3480156105b057600080fd5b506105b9610d66565b60405180826fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b34801561060157600080fd5b5061062060048036038101908080359060200190929190505050610d89565b604051808215151515815260200191505060405180910390f35b34801561064657600080fd5b5061066f6004803603810190808035906020019092919080359060200190929190505050610db2565b60405180827dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b886000819055508760018190555086600260006101000a81548160ff02191690831515021790555085600260016101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff0219169083601b0b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550846003906002610754929190610e16565b50836004908051906020019061076b929190610eaf565b508260059080519060200190610782929190610efc565b5081600660006101000a8154816fffffffffffffffffffffffffffffffff02191690837001000000000000000000000000000000009004021790555080600790805190602001906107d4929190610f7c565b507f88d23351ad32a937b11ca10530404f8297d29803e94709336b48c1f82c15b3cc898989898989898989604051808a81526020018981526020018815151515815260200187601b0b601b0b815260200186600260200280838360005b8381101561084c578082015181840152602081019050610831565b505050509050018060200180602001856fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260200180602001848103845288818151815260200191508051906020019060200280838360005b838110156108c65780820151818401526020810190506108ab565b50505050905001848103835287818151815260200191508051906020019080838360005b838110156109055780820151818401526020810190506108ea565b50505050905090810190601f1680156109325780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080516000925b8184101561099457828490602001906020020151600460200280838360005b83811015610983578082015181840152602081019050610968565b505050509050019260010192610949565b925050509c5050505050505050505050505060405180910390a1505050505050505050565b600260009054906101000a900460ff1681565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a625780601f10610a3757610100808354040283529160200191610a62565b820191906000526020600020905b815481529060010190602001808311610a4557829003601f168201915b505050505081565b600080600080610a78610fd7565b60608060006060600054600154600260009054906101000a900460ff16600260019054906101000a9004601b0b600360046005600660009054906101000a900470010000000000000000000000000000000002600784600280602002604051908101604052809291908260028015610b2a576020028201916000905b82829054906101000a900460ff16151581526020019060010190602082600001049283019260010382029150808411610af45790505b5050505050945083805480602002602001604051908101604052809291908181526020018280548015610b7c57602002820191906000526020600020905b815481526020019060010190808311610b68575b50505050509350828054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c185780601f10610bed57610100808354040283529160200191610c18565b820191906000526020600020905b815481529060010190602001808311610bfb57829003601f168201915b5050505050925080805480602002602001604051908101604052809291908181526020016000905b82821015610d0157838290600052602060002001600480602002604051908101604052809291908260048015610ced576020028201916000905b82829054906101000a90047e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060020190602082600101049283019260010382029150808411610c7a5790505b505050505081526020019060010190610c40565b505050509050985098509850985098509850985098509850909192939495969798565b60015481565b600481815481101515610d3957fe5b906000526020600020016000915090505481565b60005481565b600260019054906101000a9004601b0b81565b600660009054906101000a90047001000000000000000000000000000000000281565b600381600281101515610d9857fe5b60209182820401919006915054906101000a900460ff1681565b600782815481101515610dc157fe5b9060005260206000200181600481101515610dd857fe5b60109182820401919006600202915091509054906101000a90047e010000000000000000000000000000000000000000000000000000000000000281565b826002601f01602090048101928215610e9e5791602002820160005b83821115610e6f57835183826101000a81548160ff0219169083151502179055509260200192600101602081600001049283019260010302610e32565b8015610e9c5782816101000a81549060ff0219169055600101602081600001049283019260010302610e6f565b505b509050610eab9190610ff9565b5090565b828054828255906000526020600020908101928215610eeb579160200282015b82811115610eea578251825591602001919060010190610ecf565b5b509050610ef89190611029565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610f3d57805160ff1916838001178555610f6b565b82800160010185558215610f6b579182015b82811115610f6a578251825591602001919060010190610f4f565b5b509050610f78919061104e565b5090565b828054828255906000526020600020908101928215610fc6579160200282015b82811115610fc557825182906004610fb5929190611073565b5091602001919060010190610f9c565b5b509050610fd3919061112e565b5090565b6040805190810160405280600290602082028038833980820191505090505090565b61102691905b8082111561102257600081816101000a81549060ff021916905550600101610fff565b5090565b90565b61104b91905b8082111561104757600081600090555060010161102f565b5090565b90565b61107091905b8082111561106c576000816000905550600101611054565b5090565b90565b826004600f0160109004810192821561111d5791602002820160005b838211156110ed57835183826101000a81548161ffff02191690837e0100000000000000000000000000000000000000000000000000000000000090040217905550926020019260020160208160010104928301926001030261108f565b801561111b5782816101000a81549061ffff02191690556002016020816001010492830192600103026110ed565b505b50905061112a919061115a565b5090565b61115791905b80821115611153576000818161114a919061118b565b50600101611134565b5090565b90565b61118891905b8082111561118457600081816101000a81549061ffff021916905550600101611160565b5090565b90565b50600090555600a165627a7a7230582011b9a8b2fe6341272836fb36535a5f03b46544a58a14b17b7d49405a8247b7d10029",+  "sourceMap": "26:1413:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26:1413:0;;;;;;;",+  "deployedSourceMap": "26:1413:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;439:742;;8:9:-1;5:2;;;30:1;27;20:12;5:2;439:742:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104:19;;8:9:-1;5:2;;;30:1;27;20:12;5:2;104:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;;221:23;;8:9:-1;5:2;;;30:1;27;20:12;5:2;221:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;221:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1187:246;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1187:246:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1187:246:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1187:246:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1187:246:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1187:246:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81:17;;8:9:-1;5:2;;;30:1;27;20:12;5:2;81:17:0;;;;;;;;;;;;;;;;;;;;;;;192:23;;8:9:-1;5:2;;;30:1;27;20:12;5:2;192:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56:19;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56:19:0;;;;;;;;;;;;;;;;;;;;;;;129:23;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;250:25;;8:9:-1;5:2;;;30:1;27;20:12;5:2;250:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158:28;;8:9:-1;5:2;;;30:1;27;20:12;5:2;158:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;281:38;;8:9:-1;5:2;;;30:1;27;20:12;5:2;281:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;439:742;675:8;655:7;:28;;;;714:7;694:6;:27;;;;752:8;732:7;;:28;;;;;;;;;;;;;;;;;;791:10;771:9;;:30;;;;;;;;;;;;;;;;;;;;832:14;812:13;:34;;;;;;;:::i;:::-;;877:11;857:10;:31;;;;;;;;;;;;:::i;:::-;;919:10;899:9;:30;;;;;;;;;;;;:::i;:::-;;960:11;940:10;;:31;;;;;;;;;;;;;;;;;;;1004:20;982:19;:42;;;;;;;;;;;;:::i;:::-;;1050:124;1058:8;1068:7;1077:8;1087:10;1099:14;1115:11;1128:10;1140:11;1153:20;1050:124;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1050:124:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1050:124:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1050:124:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1050:124:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;439:742;;;;;;;;;:::o;104:19::-;;;;;;;;;;;;;:::o;221:23::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1187:246::-;1232:4;1238:3;1243:4;1249:6;1257:7;;:::i;:::-;1266:5;1273:6;1281:7;1290:11;1319:7;;1328:6;;1336:7;;;;;;;;;;;1345:9;;;;;;;;;;;1356:13;1371:10;1383:9;1394:10;;;;;;;;;;;1406:19;1311:115;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1187:246;;;;;;;;;:::o;81:17::-;;;;:::o;192:23::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;56:19::-;;;;:::o;129:23::-;;;;;;;;;;;;;:::o;250:25::-;;;;;;;;;;;;;:::o;158:28::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;281:38::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;26:1413::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;148:4;140:6;136:17;126:27;;0:157;26:1413:0;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::o",+  "source": "pragma solidity ^0.4.13;\n\ncontract ComplexStorage {\n    uint public uintVal;\n    int public intVal;\n    bool public boolVal;\n    int224 public int224Val;\n    bool[2] public boolVectorVal;\n    int[] public intListVal;\n    string public stringVal;\n    bytes16 public bytes16Val;\n    bytes2[4][] public bytes2VectorListVal;\n\n    event ValsSet(uint a, int b, bool c, int224 d, bool[2] e, int[] f, string g, bytes16 h, bytes2[4][] i);\n    \n    function setValues(uint _uintVal, int _intVal, bool _boolVal, int224 _int224Val, bool[2] _boolVectorVal, int[] _intListVal, string _stringVal, bytes16 _bytes16Val, bytes2[4][] _bytes2VectorListVal) public {\n         uintVal =           _uintVal;\n         intVal =            _intVal;\n         boolVal =           _boolVal;\n         int224Val =         _int224Val;\n         boolVectorVal =     _boolVectorVal;\n         intListVal =        _intListVal;\n         stringVal   =       _stringVal;\n         bytes16Val   =      _bytes16Val;\n         bytes2VectorListVal = _bytes2VectorListVal;\n         \n         emit ValsSet(_uintVal, _intVal, _boolVal, _int224Val, _boolVectorVal, _intListVal, _stringVal, _bytes16Val, _bytes2VectorListVal);\n    }\n\n    function getVals () constant public returns (uint, int, bool, int224, bool[2], int[], string, bytes16, bytes2[4][]) {\n      return (uintVal, intVal, boolVal, int224Val, boolVectorVal, intListVal, stringVal, bytes16Val, bytes2VectorListVal);\n    }\n   \n}\n",+  "sourcePath": "/home/akru/hsweb3test/contracts/ComplexStorage.sol",+  "ast": {+    "absolutePath": "/home/akru/hsweb3test/contracts/ComplexStorage.sol",+    "exportedSymbols": {+      "ComplexStorage": [+        167+      ]+    },+    "id": 168,+    "nodeType": "SourceUnit",+    "nodes": [+      {+        "id": 1,+        "literals": [+          "solidity",+          "^",+          "0.4",+          ".13"+        ],+        "nodeType": "PragmaDirective",+        "src": "0:24:0"+      },+      {+        "baseContracts": [],+        "contractDependencies": [],+        "contractKind": "contract",+        "documentation": null,+        "fullyImplemented": true,+        "id": 167,+        "linearizedBaseContracts": [+          167+        ],+        "name": "ComplexStorage",+        "nodeType": "ContractDefinition",+        "nodes": [+          {+            "constant": false,+            "id": 3,+            "name": "uintVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "56:19:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_uint256",+              "typeString": "uint256"+            },+            "typeName": {+              "id": 2,+              "name": "uint",+              "nodeType": "ElementaryTypeName",+              "src": "56:4:0",+              "typeDescriptions": {+                "typeIdentifier": "t_uint256",+                "typeString": "uint256"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 5,+            "name": "intVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "81:17:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_int256",+              "typeString": "int256"+            },+            "typeName": {+              "id": 4,+              "name": "int",+              "nodeType": "ElementaryTypeName",+              "src": "81:3:0",+              "typeDescriptions": {+                "typeIdentifier": "t_int256",+                "typeString": "int256"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 7,+            "name": "boolVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "104:19:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_bool",+              "typeString": "bool"+            },+            "typeName": {+              "id": 6,+              "name": "bool",+              "nodeType": "ElementaryTypeName",+              "src": "104:4:0",+              "typeDescriptions": {+                "typeIdentifier": "t_bool",+                "typeString": "bool"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 9,+            "name": "int224Val",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "129:23:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_int224",+              "typeString": "int224"+            },+            "typeName": {+              "id": 8,+              "name": "int224",+              "nodeType": "ElementaryTypeName",+              "src": "129:6:0",+              "typeDescriptions": {+                "typeIdentifier": "t_int224",+                "typeString": "int224"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 13,+            "name": "boolVectorVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "158:28:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_array$_t_bool_$2_storage",+              "typeString": "bool[2]"+            },+            "typeName": {+              "baseType": {+                "id": 10,+                "name": "bool",+                "nodeType": "ElementaryTypeName",+                "src": "158:4:0",+                "typeDescriptions": {+                  "typeIdentifier": "t_bool",+                  "typeString": "bool"+                }+              },+              "id": 12,+              "length": {+                "argumentTypes": null,+                "hexValue": "32",+                "id": 11,+                "isConstant": false,+                "isLValue": false,+                "isPure": false,+                "kind": "number",+                "lValueRequested": false,+                "nodeType": "Literal",+                "src": "163:1:0",+                "subdenomination": null,+                "typeDescriptions": {+                  "typeIdentifier": null,+                  "typeString": null+                },+                "value": "2"+              },+              "nodeType": "ArrayTypeName",+              "src": "158:7:0",+              "typeDescriptions": {+                "typeIdentifier": "t_array$_t_bool_$2_storage_ptr",+                "typeString": "bool[2]"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 16,+            "name": "intListVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "192:23:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_array$_t_int256_$dyn_storage",+              "typeString": "int256[]"+            },+            "typeName": {+              "baseType": {+                "id": 14,+                "name": "int",+                "nodeType": "ElementaryTypeName",+                "src": "192:3:0",+                "typeDescriptions": {+                  "typeIdentifier": "t_int256",+                  "typeString": "int256"+                }+              },+              "id": 15,+              "length": null,+              "nodeType": "ArrayTypeName",+              "src": "192:5:0",+              "typeDescriptions": {+                "typeIdentifier": "t_array$_t_int256_$dyn_storage_ptr",+                "typeString": "int256[]"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 18,+            "name": "stringVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "221:23:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_string_storage",+              "typeString": "string"+            },+            "typeName": {+              "id": 17,+              "name": "string",+              "nodeType": "ElementaryTypeName",+              "src": "221:6:0",+              "typeDescriptions": {+                "typeIdentifier": "t_string_storage_ptr",+                "typeString": "string"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 20,+            "name": "bytes16Val",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "250:25:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_bytes16",+              "typeString": "bytes16"+            },+            "typeName": {+              "id": 19,+              "name": "bytes16",+              "nodeType": "ElementaryTypeName",+              "src": "250:7:0",+              "typeDescriptions": {+                "typeIdentifier": "t_bytes16",+                "typeString": "bytes16"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 25,+            "name": "bytes2VectorListVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "281:38:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage",+              "typeString": "bytes2[4][]"+            },+            "typeName": {+              "baseType": {+                "baseType": {+                  "id": 21,+                  "name": "bytes2",+                  "nodeType": "ElementaryTypeName",+                  "src": "281:6:0",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes2",+                    "typeString": "bytes2"+                  }+                },+                "id": 23,+                "length": {+                  "argumentTypes": null,+                  "hexValue": "34",+                  "id": 22,+                  "isConstant": false,+                  "isLValue": false,+                  "isPure": false,+                  "kind": "number",+                  "lValueRequested": false,+                  "nodeType": "Literal",+                  "src": "288:1:0",+                  "subdenomination": null,+                  "typeDescriptions": {+                    "typeIdentifier": null,+                    "typeString": null+                  },+                  "value": "4"+                },+                "nodeType": "ArrayTypeName",+                "src": "281:9:0",+                "typeDescriptions": {+                  "typeIdentifier": "t_array$_t_bytes2_$4_storage_ptr",+                  "typeString": "bytes2[4]"+                }+              },+              "id": 24,+              "length": null,+              "nodeType": "ArrayTypeName",+              "src": "281:11:0",+              "typeDescriptions": {+                "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_ptr",+                "typeString": "bytes2[4][]"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 51,+            "name": "ValsSet",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 50,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 27,+                  "indexed": false,+                  "name": "a",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "340:6:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 26,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "340:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 29,+                  "indexed": false,+                  "name": "b",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "348:5:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int256",+                    "typeString": "int256"+                  },+                  "typeName": {+                    "id": 28,+                    "name": "int",+                    "nodeType": "ElementaryTypeName",+                    "src": "348:3:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int256",+                      "typeString": "int256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 31,+                  "indexed": false,+                  "name": "c",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "355:6:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bool",+                    "typeString": "bool"+                  },+                  "typeName": {+                    "id": 30,+                    "name": "bool",+                    "nodeType": "ElementaryTypeName",+                    "src": "355:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bool",+                      "typeString": "bool"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 33,+                  "indexed": false,+                  "name": "d",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "363:8:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int224",+                    "typeString": "int224"+                  },+                  "typeName": {+                    "id": 32,+                    "name": "int224",+                    "nodeType": "ElementaryTypeName",+                    "src": "363:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int224",+                      "typeString": "int224"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 37,+                  "indexed": false,+                  "name": "e",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "373:9:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                    "typeString": "bool[2]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 34,+                      "name": "bool",+                      "nodeType": "ElementaryTypeName",+                      "src": "373:4:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "id": 36,+                    "length": {+                      "argumentTypes": null,+                      "hexValue": "32",+                      "id": 35,+                      "isConstant": false,+                      "isLValue": false,+                      "isPure": false,+                      "kind": "number",+                      "lValueRequested": false,+                      "nodeType": "Literal",+                      "src": "378:1:0",+                      "subdenomination": null,+                      "typeDescriptions": {+                        "typeIdentifier": null,+                        "typeString": null+                      },+                      "value": "2"+                    },+                    "nodeType": "ArrayTypeName",+                    "src": "373:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_bool_$2_storage_ptr",+                      "typeString": "bool[2]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 40,+                  "indexed": false,+                  "name": "f",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "384:7:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                    "typeString": "int256[]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 38,+                      "name": "int",+                      "nodeType": "ElementaryTypeName",+                      "src": "384:3:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "id": 39,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "384:5:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_int256_$dyn_storage_ptr",+                      "typeString": "int256[]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 42,+                  "indexed": false,+                  "name": "g",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "393:8:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_string_memory_ptr",+                    "typeString": "string"+                  },+                  "typeName": {+                    "id": 41,+                    "name": "string",+                    "nodeType": "ElementaryTypeName",+                    "src": "393:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage_ptr",+                      "typeString": "string"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 44,+                  "indexed": false,+                  "name": "h",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "403:9:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes16",+                    "typeString": "bytes16"+                  },+                  "typeName": {+                    "id": 43,+                    "name": "bytes16",+                    "nodeType": "ElementaryTypeName",+                    "src": "403:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes16",+                      "typeString": "bytes16"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 49,+                  "indexed": false,+                  "name": "i",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "414:13:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                    "typeString": "bytes2[4][]"+                  },+                  "typeName": {+                    "baseType": {+                      "baseType": {+                        "id": 45,+                        "name": "bytes2",+                        "nodeType": "ElementaryTypeName",+                        "src": "414:6:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes2",+                          "typeString": "bytes2"+                        }+                      },+                      "id": 47,+                      "length": {+                        "argumentTypes": null,+                        "hexValue": "34",+                        "id": 46,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "421:1:0",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": null,+                          "typeString": null+                        },+                        "value": "4"+                      },+                      "nodeType": "ArrayTypeName",+                      "src": "414:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bytes2_$4_storage_ptr",+                        "typeString": "bytes2[4]"+                      }+                    },+                    "id": 48,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "414:11:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_ptr",+                      "typeString": "bytes2[4][]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "339:89:0"+            },+            "src": "326:103:0"+          },+          {+            "body": {+              "id": 126,+              "nodeType": "Block",+              "src": "644:537:0",+              "statements": [+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 80,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 78,+                      "name": "uintVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 3,+                      "src": "655:7:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_uint256",+                        "typeString": "uint256"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 79,+                      "name": "_uintVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 53,+                      "src": "675:8:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_uint256",+                        "typeString": "uint256"+                      }+                    },+                    "src": "655:28:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "id": 81,+                  "nodeType": "ExpressionStatement",+                  "src": "655:28:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 84,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 82,+                      "name": "intVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 5,+                      "src": "694:6:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 83,+                      "name": "_intVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 55,+                      "src": "714:7:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "src": "694:27:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int256",+                      "typeString": "int256"+                    }+                  },+                  "id": 85,+                  "nodeType": "ExpressionStatement",+                  "src": "694:27:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 88,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 86,+                      "name": "boolVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 7,+                      "src": "732:7:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 87,+                      "name": "_boolVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 57,+                      "src": "752:8:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "src": "732:28:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bool",+                      "typeString": "bool"+                    }+                  },+                  "id": 89,+                  "nodeType": "ExpressionStatement",+                  "src": "732:28:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 92,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 90,+                      "name": "int224Val",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 9,+                      "src": "771:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int224",+                        "typeString": "int224"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 91,+                      "name": "_int224Val",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 59,+                      "src": "791:10:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int224",+                        "typeString": "int224"+                      }+                    },+                    "src": "771:30:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int224",+                      "typeString": "int224"+                    }+                  },+                  "id": 93,+                  "nodeType": "ExpressionStatement",+                  "src": "771:30:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 96,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 94,+                      "name": "boolVectorVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 13,+                      "src": "812:13:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bool_$2_storage",+                        "typeString": "bool[2] storage ref"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 95,+                      "name": "_boolVectorVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 63,+                      "src": "832:14:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                        "typeString": "bool[2] memory"+                      }+                    },+                    "src": "812:34:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_bool_$2_storage",+                      "typeString": "bool[2] storage ref"+                    }+                  },+                  "id": 97,+                  "nodeType": "ExpressionStatement",+                  "src": "812:34:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 100,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 98,+                      "name": "intListVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 16,+                      "src": "857:10:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_int256_$dyn_storage",+                        "typeString": "int256[] storage ref"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 99,+                      "name": "_intListVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 66,+                      "src": "877:11:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                        "typeString": "int256[] memory"+                      }+                    },+                    "src": "857:31:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_int256_$dyn_storage",+                      "typeString": "int256[] storage ref"+                    }+                  },+                  "id": 101,+                  "nodeType": "ExpressionStatement",+                  "src": "857:31:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 104,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 102,+                      "name": "stringVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 18,+                      "src": "899:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_string_storage",+                        "typeString": "string storage ref"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 103,+                      "name": "_stringVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 68,+                      "src": "919:10:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_string_memory_ptr",+                        "typeString": "string memory"+                      }+                    },+                    "src": "899:30:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage",+                      "typeString": "string storage ref"+                    }+                  },+                  "id": 105,+                  "nodeType": "ExpressionStatement",+                  "src": "899:30:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 108,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 106,+                      "name": "bytes16Val",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 20,+                      "src": "940:10:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bytes16",+                        "typeString": "bytes16"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 107,+                      "name": "_bytes16Val",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 70,+                      "src": "960:11:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bytes16",+                        "typeString": "bytes16"+                      }+                    },+                    "src": "940:31:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes16",+                      "typeString": "bytes16"+                    }+                  },+                  "id": 109,+                  "nodeType": "ExpressionStatement",+                  "src": "940:31:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 112,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 110,+                      "name": "bytes2VectorListVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 25,+                      "src": "982:19:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage",+                        "typeString": "bytes2[4] storage ref[] storage ref"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 111,+                      "name": "_bytes2VectorListVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 75,+                      "src": "1004:20:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                        "typeString": "bytes2[4] memory[] memory"+                      }+                    },+                    "src": "982:42:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage",+                      "typeString": "bytes2[4] storage ref[] storage ref"+                    }+                  },+                  "id": 113,+                  "nodeType": "ExpressionStatement",+                  "src": "982:42:0"+                },+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "id": 115,+                        "name": "_uintVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 53,+                        "src": "1058:8:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 116,+                        "name": "_intVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 55,+                        "src": "1068:7:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_int256",+                          "typeString": "int256"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 117,+                        "name": "_boolVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 57,+                        "src": "1077:8:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bool",+                          "typeString": "bool"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 118,+                        "name": "_int224Val",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 59,+                        "src": "1087:10:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_int224",+                          "typeString": "int224"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 119,+                        "name": "_boolVectorVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 63,+                        "src": "1099:14:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                          "typeString": "bool[2] memory"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 120,+                        "name": "_intListVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 66,+                        "src": "1115:11:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                          "typeString": "int256[] memory"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 121,+                        "name": "_stringVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 68,+                        "src": "1128:10:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_string_memory_ptr",+                          "typeString": "string memory"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 122,+                        "name": "_bytes16Val",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 70,+                        "src": "1140:11:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes16",+                          "typeString": "bytes16"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 123,+                        "name": "_bytes2VectorListVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 75,+                        "src": "1153:20:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                          "typeString": "bytes2[4] memory[] memory"+                        }+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        },+                        {+                          "typeIdentifier": "t_int256",+                          "typeString": "int256"+                        },+                        {+                          "typeIdentifier": "t_bool",+                          "typeString": "bool"+                        },+                        {+                          "typeIdentifier": "t_int224",+                          "typeString": "int224"+                        },+                        {+                          "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                          "typeString": "bool[2] memory"+                        },+                        {+                          "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                          "typeString": "int256[] memory"+                        },+                        {+                          "typeIdentifier": "t_string_memory_ptr",+                          "typeString": "string memory"+                        },+                        {+                          "typeIdentifier": "t_bytes16",+                          "typeString": "bytes16"+                        },+                        {+                          "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                          "typeString": "bytes2[4] memory[] memory"+                        }+                      ],+                      "id": 114,+                      "name": "ValsSet",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 51,+                      "src": "1050:7:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_int256_$_t_bool_$_t_int224_$_t_array$_t_bool_$2_memory_ptr_$_t_array$_t_int256_$dyn_memory_ptr_$_t_string_memory_ptr_$_t_bytes16_$_t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr_$returns$__$",+                        "typeString": "function (uint256,int256,bool,int224,bool[2] memory,int256[] memory,string memory,bytes16,bytes2[4] memory[] memory)"+                      }+                    },+                    "id": 124,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "1050:124:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 125,+                  "nodeType": "EmitStatement",+                  "src": "1045:129:0"+                }+              ]+            },+            "documentation": null,+            "id": 127,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "setValues",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 76,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 53,+                  "name": "_uintVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "458:13:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 52,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "458:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 55,+                  "name": "_intVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "473:11:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int256",+                    "typeString": "int256"+                  },+                  "typeName": {+                    "id": 54,+                    "name": "int",+                    "nodeType": "ElementaryTypeName",+                    "src": "473:3:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int256",+                      "typeString": "int256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 57,+                  "name": "_boolVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "486:13:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bool",+                    "typeString": "bool"+                  },+                  "typeName": {+                    "id": 56,+                    "name": "bool",+                    "nodeType": "ElementaryTypeName",+                    "src": "486:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bool",+                      "typeString": "bool"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 59,+                  "name": "_int224Val",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "501:17:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int224",+                    "typeString": "int224"+                  },+                  "typeName": {+                    "id": 58,+                    "name": "int224",+                    "nodeType": "ElementaryTypeName",+                    "src": "501:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int224",+                      "typeString": "int224"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 63,+                  "name": "_boolVectorVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "520:22:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                    "typeString": "bool[2]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 60,+                      "name": "bool",+                      "nodeType": "ElementaryTypeName",+                      "src": "520:4:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "id": 62,+                    "length": {+                      "argumentTypes": null,+                      "hexValue": "32",+                      "id": 61,+                      "isConstant": false,+                      "isLValue": false,+                      "isPure": false,+                      "kind": "number",+                      "lValueRequested": false,+                      "nodeType": "Literal",+                      "src": "525:1:0",+                      "subdenomination": null,+                      "typeDescriptions": {+                        "typeIdentifier": null,+                        "typeString": null+                      },+                      "value": "2"+                    },+                    "nodeType": "ArrayTypeName",+                    "src": "520:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_bool_$2_storage_ptr",+                      "typeString": "bool[2]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 66,+                  "name": "_intListVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "544:17:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                    "typeString": "int256[]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 64,+                      "name": "int",+                      "nodeType": "ElementaryTypeName",+                      "src": "544:3:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "id": 65,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "544:5:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_int256_$dyn_storage_ptr",+                      "typeString": "int256[]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 68,+                  "name": "_stringVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "563:17:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_string_memory_ptr",+                    "typeString": "string"+                  },+                  "typeName": {+                    "id": 67,+                    "name": "string",+                    "nodeType": "ElementaryTypeName",+                    "src": "563:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage_ptr",+                      "typeString": "string"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 70,+                  "name": "_bytes16Val",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "582:19:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes16",+                    "typeString": "bytes16"+                  },+                  "typeName": {+                    "id": 69,+                    "name": "bytes16",+                    "nodeType": "ElementaryTypeName",+                    "src": "582:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes16",+                      "typeString": "bytes16"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 75,+                  "name": "_bytes2VectorListVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "603:32:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                    "typeString": "bytes2[4][]"+                  },+                  "typeName": {+                    "baseType": {+                      "baseType": {+                        "id": 71,+                        "name": "bytes2",+                        "nodeType": "ElementaryTypeName",+                        "src": "603:6:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes2",+                          "typeString": "bytes2"+                        }+                      },+                      "id": 73,+                      "length": {+                        "argumentTypes": null,+                        "hexValue": "34",+                        "id": 72,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "610:1:0",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": null,+                          "typeString": null+                        },+                        "value": "4"+                      },+                      "nodeType": "ArrayTypeName",+                      "src": "603:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bytes2_$4_storage_ptr",+                        "typeString": "bytes2[4]"+                      }+                    },+                    "id": 74,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "603:11:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_ptr",+                      "typeString": "bytes2[4][]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "457:179:0"+            },+            "payable": false,+            "returnParameters": {+              "id": 77,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "644:0:0"+            },+            "scope": 167,+            "src": "439:742:0",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 165,+              "nodeType": "Block",+              "src": "1303:130:0",+              "statements": [+                {+                  "expression": {+                    "argumentTypes": null,+                    "components": [+                      {+                        "argumentTypes": null,+                        "id": 154,+                        "name": "uintVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 3,+                        "src": "1319:7:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 155,+                        "name": "intVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 5,+                        "src": "1328:6:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_int256",+                          "typeString": "int256"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 156,+                        "name": "boolVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 7,+                        "src": "1336:7:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bool",+                          "typeString": "bool"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 157,+                        "name": "int224Val",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 9,+                        "src": "1345:9:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_int224",+                          "typeString": "int224"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 158,+                        "name": "boolVectorVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 13,+                        "src": "1356:13:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_bool_$2_storage",+                          "typeString": "bool[2] storage ref"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 159,+                        "name": "intListVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 16,+                        "src": "1371:10:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_int256_$dyn_storage",+                          "typeString": "int256[] storage ref"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 160,+                        "name": "stringVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 18,+                        "src": "1383:9:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_string_storage",+                          "typeString": "string storage ref"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 161,+                        "name": "bytes16Val",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 20,+                        "src": "1394:10:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes16",+                          "typeString": "bytes16"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 162,+                        "name": "bytes2VectorListVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 25,+                        "src": "1406:19:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage",+                          "typeString": "bytes2[4] storage ref[] storage ref"+                        }+                      }+                    ],+                    "id": 163,+                    "isConstant": false,+                    "isInlineArray": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "nodeType": "TupleExpression",+                    "src": "1318:108:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$_t_uint256_$_t_int256_$_t_bool_$_t_int224_$_t_array$_t_bool_$2_storage_$_t_array$_t_int256_$dyn_storage_$_t_string_storage_$_t_bytes16_$_t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_$",+                      "typeString": "tuple(uint256,int256,bool,int224,bool[2] storage ref,int256[] storage ref,string storage ref,bytes16,bytes2[4] storage ref[] storage ref)"+                    }+                  },+                  "functionReturnParameters": 153,+                  "id": 164,+                  "nodeType": "Return",+                  "src": "1311:115:0"+                }+              ]+            },+            "documentation": null,+            "id": 166,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": true,+            "modifiers": [],+            "name": "getVals",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 128,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "1204:2:0"+            },+            "payable": false,+            "returnParameters": {+              "id": 153,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 130,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1232:4:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 129,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "1232:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 132,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1238:3:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int256",+                    "typeString": "int256"+                  },+                  "typeName": {+                    "id": 131,+                    "name": "int",+                    "nodeType": "ElementaryTypeName",+                    "src": "1238:3:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int256",+                      "typeString": "int256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 134,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1243:4:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bool",+                    "typeString": "bool"+                  },+                  "typeName": {+                    "id": 133,+                    "name": "bool",+                    "nodeType": "ElementaryTypeName",+                    "src": "1243:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bool",+                      "typeString": "bool"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 136,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1249:6:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int224",+                    "typeString": "int224"+                  },+                  "typeName": {+                    "id": 135,+                    "name": "int224",+                    "nodeType": "ElementaryTypeName",+                    "src": "1249:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int224",+                      "typeString": "int224"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 140,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1257:7:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                    "typeString": "bool[2]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 137,+                      "name": "bool",+                      "nodeType": "ElementaryTypeName",+                      "src": "1257:4:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "id": 139,+                    "length": {+                      "argumentTypes": null,+                      "hexValue": "32",+                      "id": 138,+                      "isConstant": false,+                      "isLValue": false,+                      "isPure": false,+                      "kind": "number",+                      "lValueRequested": false,+                      "nodeType": "Literal",+                      "src": "1262:1:0",+                      "subdenomination": null,+                      "typeDescriptions": {+                        "typeIdentifier": null,+                        "typeString": null+                      },+                      "value": "2"+                    },+                    "nodeType": "ArrayTypeName",+                    "src": "1257:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_bool_$2_storage_ptr",+                      "typeString": "bool[2]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 143,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1266:5:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                    "typeString": "int256[]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 141,+                      "name": "int",+                      "nodeType": "ElementaryTypeName",+                      "src": "1266:3:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "id": 142,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "1266:5:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_int256_$dyn_storage_ptr",+                      "typeString": "int256[]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 145,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1273:6:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_string_memory_ptr",+                    "typeString": "string"+                  },+                  "typeName": {+                    "id": 144,+                    "name": "string",+                    "nodeType": "ElementaryTypeName",+                    "src": "1273:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage_ptr",+                      "typeString": "string"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 147,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1281:7:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes16",+                    "typeString": "bytes16"+                  },+                  "typeName": {+                    "id": 146,+                    "name": "bytes16",+                    "nodeType": "ElementaryTypeName",+                    "src": "1281:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes16",+                      "typeString": "bytes16"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 152,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1290:11:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                    "typeString": "bytes2[4][]"+                  },+                  "typeName": {+                    "baseType": {+                      "baseType": {+                        "id": 148,+                        "name": "bytes2",+                        "nodeType": "ElementaryTypeName",+                        "src": "1290:6:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes2",+                          "typeString": "bytes2"+                        }+                      },+                      "id": 150,+                      "length": {+                        "argumentTypes": null,+                        "hexValue": "34",+                        "id": 149,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "1297:1:0",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": null,+                          "typeString": null+                        },+                        "value": "4"+                      },+                      "nodeType": "ArrayTypeName",+                      "src": "1290:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bytes2_$4_storage_ptr",+                        "typeString": "bytes2[4]"+                      }+                    },+                    "id": 151,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "1290:11:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_ptr",+                      "typeString": "bytes2[4][]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "1231:71:0"+            },+            "scope": 167,+            "src": "1187:246:0",+            "stateMutability": "view",+            "superFunction": null,+            "visibility": "public"+          }+        ],+        "scope": 168,+        "src": "26:1413:0"+      }+    ],+    "src": "0:1440:0"+  },+  "legacyAST": {+    "absolutePath": "/home/akru/hsweb3test/contracts/ComplexStorage.sol",+    "exportedSymbols": {+      "ComplexStorage": [+        167+      ]+    },+    "id": 168,+    "nodeType": "SourceUnit",+    "nodes": [+      {+        "id": 1,+        "literals": [+          "solidity",+          "^",+          "0.4",+          ".13"+        ],+        "nodeType": "PragmaDirective",+        "src": "0:24:0"+      },+      {+        "baseContracts": [],+        "contractDependencies": [],+        "contractKind": "contract",+        "documentation": null,+        "fullyImplemented": true,+        "id": 167,+        "linearizedBaseContracts": [+          167+        ],+        "name": "ComplexStorage",+        "nodeType": "ContractDefinition",+        "nodes": [+          {+            "constant": false,+            "id": 3,+            "name": "uintVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "56:19:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_uint256",+              "typeString": "uint256"+            },+            "typeName": {+              "id": 2,+              "name": "uint",+              "nodeType": "ElementaryTypeName",+              "src": "56:4:0",+              "typeDescriptions": {+                "typeIdentifier": "t_uint256",+                "typeString": "uint256"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 5,+            "name": "intVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "81:17:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_int256",+              "typeString": "int256"+            },+            "typeName": {+              "id": 4,+              "name": "int",+              "nodeType": "ElementaryTypeName",+              "src": "81:3:0",+              "typeDescriptions": {+                "typeIdentifier": "t_int256",+                "typeString": "int256"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 7,+            "name": "boolVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "104:19:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_bool",+              "typeString": "bool"+            },+            "typeName": {+              "id": 6,+              "name": "bool",+              "nodeType": "ElementaryTypeName",+              "src": "104:4:0",+              "typeDescriptions": {+                "typeIdentifier": "t_bool",+                "typeString": "bool"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 9,+            "name": "int224Val",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "129:23:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_int224",+              "typeString": "int224"+            },+            "typeName": {+              "id": 8,+              "name": "int224",+              "nodeType": "ElementaryTypeName",+              "src": "129:6:0",+              "typeDescriptions": {+                "typeIdentifier": "t_int224",+                "typeString": "int224"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 13,+            "name": "boolVectorVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "158:28:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_array$_t_bool_$2_storage",+              "typeString": "bool[2]"+            },+            "typeName": {+              "baseType": {+                "id": 10,+                "name": "bool",+                "nodeType": "ElementaryTypeName",+                "src": "158:4:0",+                "typeDescriptions": {+                  "typeIdentifier": "t_bool",+                  "typeString": "bool"+                }+              },+              "id": 12,+              "length": {+                "argumentTypes": null,+                "hexValue": "32",+                "id": 11,+                "isConstant": false,+                "isLValue": false,+                "isPure": false,+                "kind": "number",+                "lValueRequested": false,+                "nodeType": "Literal",+                "src": "163:1:0",+                "subdenomination": null,+                "typeDescriptions": {+                  "typeIdentifier": null,+                  "typeString": null+                },+                "value": "2"+              },+              "nodeType": "ArrayTypeName",+              "src": "158:7:0",+              "typeDescriptions": {+                "typeIdentifier": "t_array$_t_bool_$2_storage_ptr",+                "typeString": "bool[2]"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 16,+            "name": "intListVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "192:23:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_array$_t_int256_$dyn_storage",+              "typeString": "int256[]"+            },+            "typeName": {+              "baseType": {+                "id": 14,+                "name": "int",+                "nodeType": "ElementaryTypeName",+                "src": "192:3:0",+                "typeDescriptions": {+                  "typeIdentifier": "t_int256",+                  "typeString": "int256"+                }+              },+              "id": 15,+              "length": null,+              "nodeType": "ArrayTypeName",+              "src": "192:5:0",+              "typeDescriptions": {+                "typeIdentifier": "t_array$_t_int256_$dyn_storage_ptr",+                "typeString": "int256[]"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 18,+            "name": "stringVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "221:23:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_string_storage",+              "typeString": "string"+            },+            "typeName": {+              "id": 17,+              "name": "string",+              "nodeType": "ElementaryTypeName",+              "src": "221:6:0",+              "typeDescriptions": {+                "typeIdentifier": "t_string_storage_ptr",+                "typeString": "string"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 20,+            "name": "bytes16Val",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "250:25:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_bytes16",+              "typeString": "bytes16"+            },+            "typeName": {+              "id": 19,+              "name": "bytes16",+              "nodeType": "ElementaryTypeName",+              "src": "250:7:0",+              "typeDescriptions": {+                "typeIdentifier": "t_bytes16",+                "typeString": "bytes16"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "constant": false,+            "id": 25,+            "name": "bytes2VectorListVal",+            "nodeType": "VariableDeclaration",+            "scope": 167,+            "src": "281:38:0",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage",+              "typeString": "bytes2[4][]"+            },+            "typeName": {+              "baseType": {+                "baseType": {+                  "id": 21,+                  "name": "bytes2",+                  "nodeType": "ElementaryTypeName",+                  "src": "281:6:0",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes2",+                    "typeString": "bytes2"+                  }+                },+                "id": 23,+                "length": {+                  "argumentTypes": null,+                  "hexValue": "34",+                  "id": 22,+                  "isConstant": false,+                  "isLValue": false,+                  "isPure": false,+                  "kind": "number",+                  "lValueRequested": false,+                  "nodeType": "Literal",+                  "src": "288:1:0",+                  "subdenomination": null,+                  "typeDescriptions": {+                    "typeIdentifier": null,+                    "typeString": null+                  },+                  "value": "4"+                },+                "nodeType": "ArrayTypeName",+                "src": "281:9:0",+                "typeDescriptions": {+                  "typeIdentifier": "t_array$_t_bytes2_$4_storage_ptr",+                  "typeString": "bytes2[4]"+                }+              },+              "id": 24,+              "length": null,+              "nodeType": "ArrayTypeName",+              "src": "281:11:0",+              "typeDescriptions": {+                "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_ptr",+                "typeString": "bytes2[4][]"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 51,+            "name": "ValsSet",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 50,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 27,+                  "indexed": false,+                  "name": "a",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "340:6:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 26,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "340:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 29,+                  "indexed": false,+                  "name": "b",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "348:5:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int256",+                    "typeString": "int256"+                  },+                  "typeName": {+                    "id": 28,+                    "name": "int",+                    "nodeType": "ElementaryTypeName",+                    "src": "348:3:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int256",+                      "typeString": "int256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 31,+                  "indexed": false,+                  "name": "c",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "355:6:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bool",+                    "typeString": "bool"+                  },+                  "typeName": {+                    "id": 30,+                    "name": "bool",+                    "nodeType": "ElementaryTypeName",+                    "src": "355:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bool",+                      "typeString": "bool"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 33,+                  "indexed": false,+                  "name": "d",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "363:8:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int224",+                    "typeString": "int224"+                  },+                  "typeName": {+                    "id": 32,+                    "name": "int224",+                    "nodeType": "ElementaryTypeName",+                    "src": "363:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int224",+                      "typeString": "int224"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 37,+                  "indexed": false,+                  "name": "e",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "373:9:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                    "typeString": "bool[2]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 34,+                      "name": "bool",+                      "nodeType": "ElementaryTypeName",+                      "src": "373:4:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "id": 36,+                    "length": {+                      "argumentTypes": null,+                      "hexValue": "32",+                      "id": 35,+                      "isConstant": false,+                      "isLValue": false,+                      "isPure": false,+                      "kind": "number",+                      "lValueRequested": false,+                      "nodeType": "Literal",+                      "src": "378:1:0",+                      "subdenomination": null,+                      "typeDescriptions": {+                        "typeIdentifier": null,+                        "typeString": null+                      },+                      "value": "2"+                    },+                    "nodeType": "ArrayTypeName",+                    "src": "373:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_bool_$2_storage_ptr",+                      "typeString": "bool[2]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 40,+                  "indexed": false,+                  "name": "f",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "384:7:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                    "typeString": "int256[]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 38,+                      "name": "int",+                      "nodeType": "ElementaryTypeName",+                      "src": "384:3:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "id": 39,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "384:5:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_int256_$dyn_storage_ptr",+                      "typeString": "int256[]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 42,+                  "indexed": false,+                  "name": "g",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "393:8:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_string_memory_ptr",+                    "typeString": "string"+                  },+                  "typeName": {+                    "id": 41,+                    "name": "string",+                    "nodeType": "ElementaryTypeName",+                    "src": "393:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage_ptr",+                      "typeString": "string"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 44,+                  "indexed": false,+                  "name": "h",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "403:9:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes16",+                    "typeString": "bytes16"+                  },+                  "typeName": {+                    "id": 43,+                    "name": "bytes16",+                    "nodeType": "ElementaryTypeName",+                    "src": "403:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes16",+                      "typeString": "bytes16"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 49,+                  "indexed": false,+                  "name": "i",+                  "nodeType": "VariableDeclaration",+                  "scope": 51,+                  "src": "414:13:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                    "typeString": "bytes2[4][]"+                  },+                  "typeName": {+                    "baseType": {+                      "baseType": {+                        "id": 45,+                        "name": "bytes2",+                        "nodeType": "ElementaryTypeName",+                        "src": "414:6:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes2",+                          "typeString": "bytes2"+                        }+                      },+                      "id": 47,+                      "length": {+                        "argumentTypes": null,+                        "hexValue": "34",+                        "id": 46,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "421:1:0",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": null,+                          "typeString": null+                        },+                        "value": "4"+                      },+                      "nodeType": "ArrayTypeName",+                      "src": "414:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bytes2_$4_storage_ptr",+                        "typeString": "bytes2[4]"+                      }+                    },+                    "id": 48,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "414:11:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_ptr",+                      "typeString": "bytes2[4][]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "339:89:0"+            },+            "src": "326:103:0"+          },+          {+            "body": {+              "id": 126,+              "nodeType": "Block",+              "src": "644:537:0",+              "statements": [+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 80,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 78,+                      "name": "uintVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 3,+                      "src": "655:7:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_uint256",+                        "typeString": "uint256"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 79,+                      "name": "_uintVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 53,+                      "src": "675:8:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_uint256",+                        "typeString": "uint256"+                      }+                    },+                    "src": "655:28:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "id": 81,+                  "nodeType": "ExpressionStatement",+                  "src": "655:28:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 84,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 82,+                      "name": "intVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 5,+                      "src": "694:6:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 83,+                      "name": "_intVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 55,+                      "src": "714:7:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "src": "694:27:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int256",+                      "typeString": "int256"+                    }+                  },+                  "id": 85,+                  "nodeType": "ExpressionStatement",+                  "src": "694:27:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 88,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 86,+                      "name": "boolVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 7,+                      "src": "732:7:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 87,+                      "name": "_boolVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 57,+                      "src": "752:8:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "src": "732:28:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bool",+                      "typeString": "bool"+                    }+                  },+                  "id": 89,+                  "nodeType": "ExpressionStatement",+                  "src": "732:28:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 92,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 90,+                      "name": "int224Val",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 9,+                      "src": "771:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int224",+                        "typeString": "int224"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 91,+                      "name": "_int224Val",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 59,+                      "src": "791:10:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int224",+                        "typeString": "int224"+                      }+                    },+                    "src": "771:30:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int224",+                      "typeString": "int224"+                    }+                  },+                  "id": 93,+                  "nodeType": "ExpressionStatement",+                  "src": "771:30:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 96,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 94,+                      "name": "boolVectorVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 13,+                      "src": "812:13:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bool_$2_storage",+                        "typeString": "bool[2] storage ref"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 95,+                      "name": "_boolVectorVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 63,+                      "src": "832:14:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                        "typeString": "bool[2] memory"+                      }+                    },+                    "src": "812:34:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_bool_$2_storage",+                      "typeString": "bool[2] storage ref"+                    }+                  },+                  "id": 97,+                  "nodeType": "ExpressionStatement",+                  "src": "812:34:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 100,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 98,+                      "name": "intListVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 16,+                      "src": "857:10:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_int256_$dyn_storage",+                        "typeString": "int256[] storage ref"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 99,+                      "name": "_intListVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 66,+                      "src": "877:11:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                        "typeString": "int256[] memory"+                      }+                    },+                    "src": "857:31:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_int256_$dyn_storage",+                      "typeString": "int256[] storage ref"+                    }+                  },+                  "id": 101,+                  "nodeType": "ExpressionStatement",+                  "src": "857:31:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 104,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 102,+                      "name": "stringVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 18,+                      "src": "899:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_string_storage",+                        "typeString": "string storage ref"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 103,+                      "name": "_stringVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 68,+                      "src": "919:10:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_string_memory_ptr",+                        "typeString": "string memory"+                      }+                    },+                    "src": "899:30:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage",+                      "typeString": "string storage ref"+                    }+                  },+                  "id": 105,+                  "nodeType": "ExpressionStatement",+                  "src": "899:30:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 108,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 106,+                      "name": "bytes16Val",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 20,+                      "src": "940:10:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bytes16",+                        "typeString": "bytes16"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 107,+                      "name": "_bytes16Val",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 70,+                      "src": "960:11:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bytes16",+                        "typeString": "bytes16"+                      }+                    },+                    "src": "940:31:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes16",+                      "typeString": "bytes16"+                    }+                  },+                  "id": 109,+                  "nodeType": "ExpressionStatement",+                  "src": "940:31:0"+                },+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 112,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 110,+                      "name": "bytes2VectorListVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 25,+                      "src": "982:19:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage",+                        "typeString": "bytes2[4] storage ref[] storage ref"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 111,+                      "name": "_bytes2VectorListVal",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 75,+                      "src": "1004:20:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                        "typeString": "bytes2[4] memory[] memory"+                      }+                    },+                    "src": "982:42:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage",+                      "typeString": "bytes2[4] storage ref[] storage ref"+                    }+                  },+                  "id": 113,+                  "nodeType": "ExpressionStatement",+                  "src": "982:42:0"+                },+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "id": 115,+                        "name": "_uintVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 53,+                        "src": "1058:8:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 116,+                        "name": "_intVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 55,+                        "src": "1068:7:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_int256",+                          "typeString": "int256"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 117,+                        "name": "_boolVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 57,+                        "src": "1077:8:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bool",+                          "typeString": "bool"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 118,+                        "name": "_int224Val",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 59,+                        "src": "1087:10:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_int224",+                          "typeString": "int224"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 119,+                        "name": "_boolVectorVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 63,+                        "src": "1099:14:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                          "typeString": "bool[2] memory"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 120,+                        "name": "_intListVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 66,+                        "src": "1115:11:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                          "typeString": "int256[] memory"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 121,+                        "name": "_stringVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 68,+                        "src": "1128:10:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_string_memory_ptr",+                          "typeString": "string memory"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 122,+                        "name": "_bytes16Val",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 70,+                        "src": "1140:11:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes16",+                          "typeString": "bytes16"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 123,+                        "name": "_bytes2VectorListVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 75,+                        "src": "1153:20:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                          "typeString": "bytes2[4] memory[] memory"+                        }+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        },+                        {+                          "typeIdentifier": "t_int256",+                          "typeString": "int256"+                        },+                        {+                          "typeIdentifier": "t_bool",+                          "typeString": "bool"+                        },+                        {+                          "typeIdentifier": "t_int224",+                          "typeString": "int224"+                        },+                        {+                          "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                          "typeString": "bool[2] memory"+                        },+                        {+                          "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                          "typeString": "int256[] memory"+                        },+                        {+                          "typeIdentifier": "t_string_memory_ptr",+                          "typeString": "string memory"+                        },+                        {+                          "typeIdentifier": "t_bytes16",+                          "typeString": "bytes16"+                        },+                        {+                          "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                          "typeString": "bytes2[4] memory[] memory"+                        }+                      ],+                      "id": 114,+                      "name": "ValsSet",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 51,+                      "src": "1050:7:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_int256_$_t_bool_$_t_int224_$_t_array$_t_bool_$2_memory_ptr_$_t_array$_t_int256_$dyn_memory_ptr_$_t_string_memory_ptr_$_t_bytes16_$_t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr_$returns$__$",+                        "typeString": "function (uint256,int256,bool,int224,bool[2] memory,int256[] memory,string memory,bytes16,bytes2[4] memory[] memory)"+                      }+                    },+                    "id": 124,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "1050:124:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 125,+                  "nodeType": "EmitStatement",+                  "src": "1045:129:0"+                }+              ]+            },+            "documentation": null,+            "id": 127,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "setValues",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 76,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 53,+                  "name": "_uintVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "458:13:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 52,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "458:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 55,+                  "name": "_intVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "473:11:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int256",+                    "typeString": "int256"+                  },+                  "typeName": {+                    "id": 54,+                    "name": "int",+                    "nodeType": "ElementaryTypeName",+                    "src": "473:3:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int256",+                      "typeString": "int256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 57,+                  "name": "_boolVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "486:13:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bool",+                    "typeString": "bool"+                  },+                  "typeName": {+                    "id": 56,+                    "name": "bool",+                    "nodeType": "ElementaryTypeName",+                    "src": "486:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bool",+                      "typeString": "bool"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 59,+                  "name": "_int224Val",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "501:17:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int224",+                    "typeString": "int224"+                  },+                  "typeName": {+                    "id": 58,+                    "name": "int224",+                    "nodeType": "ElementaryTypeName",+                    "src": "501:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int224",+                      "typeString": "int224"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 63,+                  "name": "_boolVectorVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "520:22:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                    "typeString": "bool[2]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 60,+                      "name": "bool",+                      "nodeType": "ElementaryTypeName",+                      "src": "520:4:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "id": 62,+                    "length": {+                      "argumentTypes": null,+                      "hexValue": "32",+                      "id": 61,+                      "isConstant": false,+                      "isLValue": false,+                      "isPure": false,+                      "kind": "number",+                      "lValueRequested": false,+                      "nodeType": "Literal",+                      "src": "525:1:0",+                      "subdenomination": null,+                      "typeDescriptions": {+                        "typeIdentifier": null,+                        "typeString": null+                      },+                      "value": "2"+                    },+                    "nodeType": "ArrayTypeName",+                    "src": "520:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_bool_$2_storage_ptr",+                      "typeString": "bool[2]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 66,+                  "name": "_intListVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "544:17:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                    "typeString": "int256[]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 64,+                      "name": "int",+                      "nodeType": "ElementaryTypeName",+                      "src": "544:3:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "id": 65,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "544:5:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_int256_$dyn_storage_ptr",+                      "typeString": "int256[]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 68,+                  "name": "_stringVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "563:17:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_string_memory_ptr",+                    "typeString": "string"+                  },+                  "typeName": {+                    "id": 67,+                    "name": "string",+                    "nodeType": "ElementaryTypeName",+                    "src": "563:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage_ptr",+                      "typeString": "string"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 70,+                  "name": "_bytes16Val",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "582:19:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes16",+                    "typeString": "bytes16"+                  },+                  "typeName": {+                    "id": 69,+                    "name": "bytes16",+                    "nodeType": "ElementaryTypeName",+                    "src": "582:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes16",+                      "typeString": "bytes16"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 75,+                  "name": "_bytes2VectorListVal",+                  "nodeType": "VariableDeclaration",+                  "scope": 127,+                  "src": "603:32:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                    "typeString": "bytes2[4][]"+                  },+                  "typeName": {+                    "baseType": {+                      "baseType": {+                        "id": 71,+                        "name": "bytes2",+                        "nodeType": "ElementaryTypeName",+                        "src": "603:6:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes2",+                          "typeString": "bytes2"+                        }+                      },+                      "id": 73,+                      "length": {+                        "argumentTypes": null,+                        "hexValue": "34",+                        "id": 72,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "610:1:0",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": null,+                          "typeString": null+                        },+                        "value": "4"+                      },+                      "nodeType": "ArrayTypeName",+                      "src": "603:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bytes2_$4_storage_ptr",+                        "typeString": "bytes2[4]"+                      }+                    },+                    "id": 74,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "603:11:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_ptr",+                      "typeString": "bytes2[4][]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "457:179:0"+            },+            "payable": false,+            "returnParameters": {+              "id": 77,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "644:0:0"+            },+            "scope": 167,+            "src": "439:742:0",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 165,+              "nodeType": "Block",+              "src": "1303:130:0",+              "statements": [+                {+                  "expression": {+                    "argumentTypes": null,+                    "components": [+                      {+                        "argumentTypes": null,+                        "id": 154,+                        "name": "uintVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 3,+                        "src": "1319:7:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 155,+                        "name": "intVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 5,+                        "src": "1328:6:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_int256",+                          "typeString": "int256"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 156,+                        "name": "boolVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 7,+                        "src": "1336:7:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bool",+                          "typeString": "bool"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 157,+                        "name": "int224Val",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 9,+                        "src": "1345:9:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_int224",+                          "typeString": "int224"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 158,+                        "name": "boolVectorVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 13,+                        "src": "1356:13:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_bool_$2_storage",+                          "typeString": "bool[2] storage ref"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 159,+                        "name": "intListVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 16,+                        "src": "1371:10:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_int256_$dyn_storage",+                          "typeString": "int256[] storage ref"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 160,+                        "name": "stringVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 18,+                        "src": "1383:9:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_string_storage",+                          "typeString": "string storage ref"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 161,+                        "name": "bytes16Val",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 20,+                        "src": "1394:10:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes16",+                          "typeString": "bytes16"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "id": 162,+                        "name": "bytes2VectorListVal",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 25,+                        "src": "1406:19:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage",+                          "typeString": "bytes2[4] storage ref[] storage ref"+                        }+                      }+                    ],+                    "id": 163,+                    "isConstant": false,+                    "isInlineArray": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "nodeType": "TupleExpression",+                    "src": "1318:108:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$_t_uint256_$_t_int256_$_t_bool_$_t_int224_$_t_array$_t_bool_$2_storage_$_t_array$_t_int256_$dyn_storage_$_t_string_storage_$_t_bytes16_$_t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_$",+                      "typeString": "tuple(uint256,int256,bool,int224,bool[2] storage ref,int256[] storage ref,string storage ref,bytes16,bytes2[4] storage ref[] storage ref)"+                    }+                  },+                  "functionReturnParameters": 153,+                  "id": 164,+                  "nodeType": "Return",+                  "src": "1311:115:0"+                }+              ]+            },+            "documentation": null,+            "id": 166,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": true,+            "modifiers": [],+            "name": "getVals",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 128,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "1204:2:0"+            },+            "payable": false,+            "returnParameters": {+              "id": 153,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 130,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1232:4:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 129,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "1232:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 132,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1238:3:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int256",+                    "typeString": "int256"+                  },+                  "typeName": {+                    "id": 131,+                    "name": "int",+                    "nodeType": "ElementaryTypeName",+                    "src": "1238:3:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int256",+                      "typeString": "int256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 134,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1243:4:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bool",+                    "typeString": "bool"+                  },+                  "typeName": {+                    "id": 133,+                    "name": "bool",+                    "nodeType": "ElementaryTypeName",+                    "src": "1243:4:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bool",+                      "typeString": "bool"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 136,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1249:6:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_int224",+                    "typeString": "int224"+                  },+                  "typeName": {+                    "id": 135,+                    "name": "int224",+                    "nodeType": "ElementaryTypeName",+                    "src": "1249:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_int224",+                      "typeString": "int224"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 140,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1257:7:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_bool_$2_memory_ptr",+                    "typeString": "bool[2]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 137,+                      "name": "bool",+                      "nodeType": "ElementaryTypeName",+                      "src": "1257:4:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_bool",+                        "typeString": "bool"+                      }+                    },+                    "id": 139,+                    "length": {+                      "argumentTypes": null,+                      "hexValue": "32",+                      "id": 138,+                      "isConstant": false,+                      "isLValue": false,+                      "isPure": false,+                      "kind": "number",+                      "lValueRequested": false,+                      "nodeType": "Literal",+                      "src": "1262:1:0",+                      "subdenomination": null,+                      "typeDescriptions": {+                        "typeIdentifier": null,+                        "typeString": null+                      },+                      "value": "2"+                    },+                    "nodeType": "ArrayTypeName",+                    "src": "1257:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_bool_$2_storage_ptr",+                      "typeString": "bool[2]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 143,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1266:5:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_int256_$dyn_memory_ptr",+                    "typeString": "int256[]"+                  },+                  "typeName": {+                    "baseType": {+                      "id": 141,+                      "name": "int",+                      "nodeType": "ElementaryTypeName",+                      "src": "1266:3:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_int256",+                        "typeString": "int256"+                      }+                    },+                    "id": 142,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "1266:5:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_int256_$dyn_storage_ptr",+                      "typeString": "int256[]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 145,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1273:6:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_string_memory_ptr",+                    "typeString": "string"+                  },+                  "typeName": {+                    "id": 144,+                    "name": "string",+                    "nodeType": "ElementaryTypeName",+                    "src": "1273:6:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage_ptr",+                      "typeString": "string"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 147,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1281:7:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes16",+                    "typeString": "bytes16"+                  },+                  "typeName": {+                    "id": 146,+                    "name": "bytes16",+                    "nodeType": "ElementaryTypeName",+                    "src": "1281:7:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes16",+                      "typeString": "bytes16"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 152,+                  "name": "",+                  "nodeType": "VariableDeclaration",+                  "scope": 166,+                  "src": "1290:11:0",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_memory_$dyn_memory_ptr",+                    "typeString": "bytes2[4][]"+                  },+                  "typeName": {+                    "baseType": {+                      "baseType": {+                        "id": 148,+                        "name": "bytes2",+                        "nodeType": "ElementaryTypeName",+                        "src": "1290:6:0",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes2",+                          "typeString": "bytes2"+                        }+                      },+                      "id": 150,+                      "length": {+                        "argumentTypes": null,+                        "hexValue": "34",+                        "id": 149,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "1297:1:0",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": null,+                          "typeString": null+                        },+                        "value": "4"+                      },+                      "nodeType": "ArrayTypeName",+                      "src": "1290:9:0",+                      "typeDescriptions": {+                        "typeIdentifier": "t_array$_t_bytes2_$4_storage_ptr",+                        "typeString": "bytes2[4]"+                      }+                    },+                    "id": 151,+                    "length": null,+                    "nodeType": "ArrayTypeName",+                    "src": "1290:11:0",+                    "typeDescriptions": {+                      "typeIdentifier": "t_array$_t_array$_t_bytes2_$4_storage_$dyn_storage_ptr",+                      "typeString": "bytes2[4][]"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "1231:71:0"+            },+            "scope": 167,+            "src": "1187:246:0",+            "stateMutability": "view",+            "superFunction": null,+            "visibility": "public"+          }+        ],+        "scope": 168,+        "src": "26:1413:0"+      }+    ],+    "src": "0:1440:0"+  },+  "compiler": {+    "name": "solc",+    "version": "0.4.24+commit.e67f0147.Emscripten.clang"+  },+  "networks": {},+  "schemaVersion": "2.0.1",+  "updatedAt": "2018-10-17T08:28:45.994Z"+}
+ test/contracts/Linearization.json view
@@ -0,0 +1,2716 @@+{+  "contractName": "Linearization",+  "abi": [+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": false,+          "name": "sender",+          "type": "address"+        },+        {+          "indexed": false,+          "name": "amount",+          "type": "uint256"+        }+      ],+      "name": "E1",+      "type": "event"+    },+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": false,+          "name": "tag",+          "type": "string"+        },+        {+          "indexed": false,+          "name": "uuid",+          "type": "bytes4"+        }+      ],+      "name": "E2",+      "type": "event"+    },+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": false,+          "name": "txOrigin",+          "type": "address"+        },+        {+          "indexed": false,+          "name": "blockNumber",+          "type": "uint256"+        }+      ],+      "name": "E3",+      "type": "event"+    },+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": false,+          "name": "sig",+          "type": "bytes4"+        },+        {+          "indexed": false,+          "name": "blockHash",+          "type": "bytes32"+        }+      ],+      "name": "E4",+      "type": "event"+    },+    {+      "constant": false,+      "inputs": [],+      "name": "e12",+      "outputs": [],+      "payable": false,+      "stateMutability": "nonpayable",+      "type": "function"+    },+    {+      "constant": false,+      "inputs": [],+      "name": "e21",+      "outputs": [],+      "payable": false,+      "stateMutability": "nonpayable",+      "type": "function"+    },+    {+      "constant": false,+      "inputs": [],+      "name": "e1",+      "outputs": [],+      "payable": false,+      "stateMutability": "nonpayable",+      "type": "function"+    },+    {+      "constant": false,+      "inputs": [],+      "name": "e2",+      "outputs": [],+      "payable": false,+      "stateMutability": "nonpayable",+      "type": "function"+    },+    {+      "constant": false,+      "inputs": [],+      "name": "e3",+      "outputs": [],+      "payable": false,+      "stateMutability": "nonpayable",+      "type": "function"+    },+    {+      "constant": false,+      "inputs": [],+      "name": "e4",+      "outputs": [],+      "payable": false,+      "stateMutability": "nonpayable",+      "type": "function"+    }+  ],+  "bytecode": "0x608060405234801561001057600080fd5b506105ad806100206000396000f300608060405260043610610077576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168062def0b21461007c57806356800b521461009357806379e5f054146100aa5780639b31f9e8146100c1578063a0f29798146100d8578063a2c2d666146100ef575b600080fd5b34801561008857600080fd5b50610091610106565b005b34801561009f57600080fd5b506100a8610226565b005b3480156100b657600080fd5b506100bf610293565b005b3480156100cd57600080fd5b506100d661033f565b005b3480156100e457600080fd5b506100ed6103f3565b005b3480156100fb57600080fd5b50610104610513565b005b7f39be10caf08413c53cba369135da2b641931c99ac27b0d821e26f3ec4e0c63d2336000604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a17fa7070e1659496fddc8e134f7c9c487aba246b54d9a23918210a30bfa32af9e4563deadbeef6040518080602001837c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001828103825260058152602001807f68656c6c6f0000000000000000000000000000000000000000000000000000008152506020019250505060405180910390a1565b7fe86793c401899b62baf9c8e9b8a8803ece6ace1021d056fe8634d1f59a0410c13243604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1565b7fd8f3042e770b7de0dc534d3accbe98fba747e05ada6febe1a03d1e098521edc26000357fffffffff0000000000000000000000000000000000000000000000000000000016434060405180837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200182600019166000191681526020019250505060405180910390a1565b7fa7070e1659496fddc8e134f7c9c487aba246b54d9a23918210a30bfa32af9e4563deadbeef6040518080602001837c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001828103825260058152602001807f68656c6c6f0000000000000000000000000000000000000000000000000000008152506020019250505060405180910390a1565b7fa7070e1659496fddc8e134f7c9c487aba246b54d9a23918210a30bfa32af9e4563deadbeef6040518080602001837c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001828103825260058152602001807f68656c6c6f0000000000000000000000000000000000000000000000000000008152506020019250505060405180910390a17f39be10caf08413c53cba369135da2b641931c99ac27b0d821e26f3ec4e0c63d2336000604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1565b7f39be10caf08413c53cba369135da2b641931c99ac27b0d821e26f3ec4e0c63d2336000604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15600a165627a7a72305820be9afa4ce385da787f13197a249b8d9d1c557381e3c46f9bbada45913eee79870029",+  "deployedBytecode": "0x608060405260043610610077576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168062def0b21461007c57806356800b521461009357806379e5f054146100aa5780639b31f9e8146100c1578063a0f29798146100d8578063a2c2d666146100ef575b600080fd5b34801561008857600080fd5b50610091610106565b005b34801561009f57600080fd5b506100a8610226565b005b3480156100b657600080fd5b506100bf610293565b005b3480156100cd57600080fd5b506100d661033f565b005b3480156100e457600080fd5b506100ed6103f3565b005b3480156100fb57600080fd5b50610104610513565b005b7f39be10caf08413c53cba369135da2b641931c99ac27b0d821e26f3ec4e0c63d2336000604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a17fa7070e1659496fddc8e134f7c9c487aba246b54d9a23918210a30bfa32af9e4563deadbeef6040518080602001837c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001828103825260058152602001807f68656c6c6f0000000000000000000000000000000000000000000000000000008152506020019250505060405180910390a1565b7fe86793c401899b62baf9c8e9b8a8803ece6ace1021d056fe8634d1f59a0410c13243604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1565b7fd8f3042e770b7de0dc534d3accbe98fba747e05ada6febe1a03d1e098521edc26000357fffffffff0000000000000000000000000000000000000000000000000000000016434060405180837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200182600019166000191681526020019250505060405180910390a1565b7fa7070e1659496fddc8e134f7c9c487aba246b54d9a23918210a30bfa32af9e4563deadbeef6040518080602001837c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001828103825260058152602001807f68656c6c6f0000000000000000000000000000000000000000000000000000008152506020019250505060405180910390a1565b7fa7070e1659496fddc8e134f7c9c487aba246b54d9a23918210a30bfa32af9e4563deadbeef6040518080602001837c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001828103825260058152602001807f68656c6c6f0000000000000000000000000000000000000000000000000000008152506020019250505060405180910390a17f39be10caf08413c53cba369135da2b641931c99ac27b0d821e26f3ec4e0c63d2336000604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1565b7f39be10caf08413c53cba369135da2b641931c99ac27b0d821e26f3ec4e0c63d2336000604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15600a165627a7a72305820be9afa4ce385da787f13197a249b8d9d1c557381e3c46f9bbada45913eee79870029",+  "sourceMap": "26:649:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26:649:1;;;;;;;",+  "deployedSourceMap": "26:649:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;224:89;;8:9:-1;5:2;;;30:1;27;20:12;5:2;224:89:1;;;;;;532:64;;8:9:-1;5:2;;;30:1;27;20:12;5:2;532:64:1;;;;;;600:73;;8:9:-1;5:2;;;30:1;27;20:12;5:2;600:73:1;;;;;;468:60;;8:9:-1;5:2;;;30:1;27;20:12;5:2;468:60:1;;;;;;317:89;;8:9:-1;5:2;;;30:1;27;20:12;5:2;317:89:1;;;;;;410:54;;8:9:-1;5:2;;;30:1;27;20:12;5:2;410:54:1;;;;;;224:89;257:17;260:10;272:1;257:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;285:23;297:10;285:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;224:89::o;532:64::-;564:27;567:9;578:12;564:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;532:64::o;600:73::-;632:36;635:7;;;;654:12;644:23;632:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;600:73::o;468:60::-;500:23;512:10;500:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;468:60::o;317:89::-;350:23;362:10;350:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;384:17;387:10;399:1;384:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;317:89::o;410:54::-;442:17;445:10;457:1;442:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;410:54::o",+  "source": "pragma solidity ^0.4.22;\n\ncontract Linearization {\n\n  event E1(address sender, uint amount);\n  event E2(string tag, bytes4 uuid);\n  event E3(address txOrigin, uint blockNumber);\n  event E4(bytes4 sig, bytes32 blockHash);\n\n  function e12() public {\n    emit E1(msg.sender, 0);\n    emit E2(\"hello\", 0xdeadbeef);\n  }\n\n  function e21() public {\n    emit E2(\"hello\", 0xdeadbeef);\n    emit E1(msg.sender, 0);\n  }\n\n  function e1() public {\n    emit E1(msg.sender, 0);\n  }\n\n  function e2() public {\n    emit E2(\"hello\", 0xdeadbeef);\n  }\n\n  function e3() public {\n    emit E3(tx.origin, block.number);\n  }\n\n  function e4() public {\n    emit E4(msg.sig, blockhash(block.number));\n  }\n}",+  "sourcePath": "/home/akru/hsweb3test/contracts/Linearization.sol",+  "ast": {+    "absolutePath": "/home/akru/hsweb3test/contracts/Linearization.sol",+    "exportedSymbols": {+      "Linearization": [+        267+      ]+    },+    "id": 268,+    "nodeType": "SourceUnit",+    "nodes": [+      {+        "id": 169,+        "literals": [+          "solidity",+          "^",+          "0.4",+          ".22"+        ],+        "nodeType": "PragmaDirective",+        "src": "0:24:1"+      },+      {+        "baseContracts": [],+        "contractDependencies": [],+        "contractKind": "contract",+        "documentation": null,+        "fullyImplemented": true,+        "id": 267,+        "linearizedBaseContracts": [+          267+        ],+        "name": "Linearization",+        "nodeType": "ContractDefinition",+        "nodes": [+          {+            "anonymous": false,+            "documentation": null,+            "id": 175,+            "name": "E1",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 174,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 171,+                  "indexed": false,+                  "name": "sender",+                  "nodeType": "VariableDeclaration",+                  "scope": 175,+                  "src": "63:14:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_address",+                    "typeString": "address"+                  },+                  "typeName": {+                    "id": 170,+                    "name": "address",+                    "nodeType": "ElementaryTypeName",+                    "src": "63:7:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_address",+                      "typeString": "address"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 173,+                  "indexed": false,+                  "name": "amount",+                  "nodeType": "VariableDeclaration",+                  "scope": 175,+                  "src": "79:11:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 172,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "79:4:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "62:29:1"+            },+            "src": "54:38:1"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 181,+            "name": "E2",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 180,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 177,+                  "indexed": false,+                  "name": "tag",+                  "nodeType": "VariableDeclaration",+                  "scope": 181,+                  "src": "104:10:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_string_memory_ptr",+                    "typeString": "string"+                  },+                  "typeName": {+                    "id": 176,+                    "name": "string",+                    "nodeType": "ElementaryTypeName",+                    "src": "104:6:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage_ptr",+                      "typeString": "string"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 179,+                  "indexed": false,+                  "name": "uuid",+                  "nodeType": "VariableDeclaration",+                  "scope": 181,+                  "src": "116:11:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes4",+                    "typeString": "bytes4"+                  },+                  "typeName": {+                    "id": 178,+                    "name": "bytes4",+                    "nodeType": "ElementaryTypeName",+                    "src": "116:6:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes4",+                      "typeString": "bytes4"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "103:25:1"+            },+            "src": "95:34:1"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 187,+            "name": "E3",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 186,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 183,+                  "indexed": false,+                  "name": "txOrigin",+                  "nodeType": "VariableDeclaration",+                  "scope": 187,+                  "src": "141:16:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_address",+                    "typeString": "address"+                  },+                  "typeName": {+                    "id": 182,+                    "name": "address",+                    "nodeType": "ElementaryTypeName",+                    "src": "141:7:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_address",+                      "typeString": "address"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 185,+                  "indexed": false,+                  "name": "blockNumber",+                  "nodeType": "VariableDeclaration",+                  "scope": 187,+                  "src": "159:16:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 184,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "159:4:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "140:36:1"+            },+            "src": "132:45:1"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 193,+            "name": "E4",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 192,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 189,+                  "indexed": false,+                  "name": "sig",+                  "nodeType": "VariableDeclaration",+                  "scope": 193,+                  "src": "189:10:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes4",+                    "typeString": "bytes4"+                  },+                  "typeName": {+                    "id": 188,+                    "name": "bytes4",+                    "nodeType": "ElementaryTypeName",+                    "src": "189:6:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes4",+                      "typeString": "bytes4"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 191,+                  "indexed": false,+                  "name": "blockHash",+                  "nodeType": "VariableDeclaration",+                  "scope": 193,+                  "src": "201:17:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes32",+                    "typeString": "bytes32"+                  },+                  "typeName": {+                    "id": 190,+                    "name": "bytes32",+                    "nodeType": "ElementaryTypeName",+                    "src": "201:7:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes32",+                      "typeString": "bytes32"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "188:31:1"+            },+            "src": "180:40:1"+          },+          {+            "body": {+              "id": 207,+              "nodeType": "Block",+              "src": "246:67:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 197,+                          "name": "msg",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 381,+                          "src": "260:3:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_message",+                            "typeString": "msg"+                          }+                        },+                        "id": 198,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "sender",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "260:10:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30",+                        "id": 199,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "272:1:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        },+                        "value": "0"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        },+                        {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        }+                      ],+                      "id": 196,+                      "name": "E1",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 175,+                      "src": "257:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$",+                        "typeString": "function (address,uint256)"+                      }+                    },+                    "id": 200,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "257:17:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 201,+                  "nodeType": "EmitStatement",+                  "src": "252:22:1"+                },+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "hexValue": "68656c6c6f",+                        "id": 203,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "string",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "288:7:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        "value": "hello"+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30786465616462656566",+                        "id": 204,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "297:10:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        },+                        "value": "0xdeadbeef"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        }+                      ],+                      "id": 202,+                      "name": "E2",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 181,+                      "src": "285:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_bytes4_$returns$__$",+                        "typeString": "function (string memory,bytes4)"+                      }+                    },+                    "id": 205,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "285:23:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 206,+                  "nodeType": "EmitStatement",+                  "src": "280:28:1"+                }+              ]+            },+            "documentation": null,+            "id": 208,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e12",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 194,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "236:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 195,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "246:0:1"+            },+            "scope": 267,+            "src": "224:89:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 222,+              "nodeType": "Block",+              "src": "339:67:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "hexValue": "68656c6c6f",+                        "id": 212,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "string",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "353:7:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        "value": "hello"+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30786465616462656566",+                        "id": 213,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "362:10:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        },+                        "value": "0xdeadbeef"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        }+                      ],+                      "id": 211,+                      "name": "E2",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 181,+                      "src": "350:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_bytes4_$returns$__$",+                        "typeString": "function (string memory,bytes4)"+                      }+                    },+                    "id": 214,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "350:23:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 215,+                  "nodeType": "EmitStatement",+                  "src": "345:28:1"+                },+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 217,+                          "name": "msg",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 381,+                          "src": "387:3:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_message",+                            "typeString": "msg"+                          }+                        },+                        "id": 218,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "sender",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "387:10:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30",+                        "id": 219,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "399:1:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        },+                        "value": "0"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        },+                        {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        }+                      ],+                      "id": 216,+                      "name": "E1",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 175,+                      "src": "384:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$",+                        "typeString": "function (address,uint256)"+                      }+                    },+                    "id": 220,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "384:17:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 221,+                  "nodeType": "EmitStatement",+                  "src": "379:22:1"+                }+              ]+            },+            "documentation": null,+            "id": 223,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e21",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 209,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "329:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 210,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "339:0:1"+            },+            "scope": 267,+            "src": "317:89:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 232,+              "nodeType": "Block",+              "src": "431:33:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 227,+                          "name": "msg",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 381,+                          "src": "445:3:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_message",+                            "typeString": "msg"+                          }+                        },+                        "id": 228,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "sender",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "445:10:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30",+                        "id": 229,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "457:1:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        },+                        "value": "0"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        },+                        {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        }+                      ],+                      "id": 226,+                      "name": "E1",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 175,+                      "src": "442:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$",+                        "typeString": "function (address,uint256)"+                      }+                    },+                    "id": 230,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "442:17:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 231,+                  "nodeType": "EmitStatement",+                  "src": "437:22:1"+                }+              ]+            },+            "documentation": null,+            "id": 233,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e1",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 224,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "421:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 225,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "431:0:1"+            },+            "scope": 267,+            "src": "410:54:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 241,+              "nodeType": "Block",+              "src": "489:39:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "hexValue": "68656c6c6f",+                        "id": 237,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "string",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "503:7:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        "value": "hello"+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30786465616462656566",+                        "id": 238,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "512:10:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        },+                        "value": "0xdeadbeef"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        }+                      ],+                      "id": 236,+                      "name": "E2",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 181,+                      "src": "500:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_bytes4_$returns$__$",+                        "typeString": "function (string memory,bytes4)"+                      }+                    },+                    "id": 239,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "500:23:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 240,+                  "nodeType": "EmitStatement",+                  "src": "495:28:1"+                }+              ]+            },+            "documentation": null,+            "id": 242,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e2",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 234,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "479:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 235,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "489:0:1"+            },+            "scope": 267,+            "src": "468:60:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 252,+              "nodeType": "Block",+              "src": "553:43:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 246,+                          "name": "tx",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 393,+                          "src": "567:2:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_transaction",+                            "typeString": "tx"+                          }+                        },+                        "id": 247,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "origin",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "567:9:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 248,+                          "name": "block",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 371,+                          "src": "578:5:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_block",+                            "typeString": "block"+                          }+                        },+                        "id": 249,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "number",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "578:12:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        },+                        {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      ],+                      "id": 245,+                      "name": "E3",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 187,+                      "src": "564:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$",+                        "typeString": "function (address,uint256)"+                      }+                    },+                    "id": 250,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "564:27:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 251,+                  "nodeType": "EmitStatement",+                  "src": "559:32:1"+                }+              ]+            },+            "documentation": null,+            "id": 253,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e3",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 243,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "543:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 244,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "553:0:1"+            },+            "scope": 267,+            "src": "532:64:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 265,+              "nodeType": "Block",+              "src": "621:52:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 257,+                          "name": "msg",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 381,+                          "src": "635:3:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_message",+                            "typeString": "msg"+                          }+                        },+                        "id": 258,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "sig",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "635:7:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes4",+                          "typeString": "bytes4"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "arguments": [+                          {+                            "argumentTypes": null,+                            "expression": {+                              "argumentTypes": null,+                              "id": 260,+                              "name": "block",+                              "nodeType": "Identifier",+                              "overloadedDeclarations": [],+                              "referencedDeclaration": 371,+                              "src": "654:5:1",+                              "typeDescriptions": {+                                "typeIdentifier": "t_magic_block",+                                "typeString": "block"+                              }+                            },+                            "id": 261,+                            "isConstant": false,+                            "isLValue": false,+                            "isPure": false,+                            "lValueRequested": false,+                            "memberName": "number",+                            "nodeType": "MemberAccess",+                            "referencedDeclaration": null,+                            "src": "654:12:1",+                            "typeDescriptions": {+                              "typeIdentifier": "t_uint256",+                              "typeString": "uint256"+                            }+                          }+                        ],+                        "expression": {+                          "argumentTypes": [+                            {+                              "typeIdentifier": "t_uint256",+                              "typeString": "uint256"+                            }+                          ],+                          "id": 259,+                          "name": "blockhash",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 372,+                          "src": "644:9:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_function_blockhash_view$_t_uint256_$returns$_t_bytes32_$",+                            "typeString": "function (uint256) view returns (bytes32)"+                          }+                        },+                        "id": 262,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "kind": "functionCall",+                        "lValueRequested": false,+                        "names": [],+                        "nodeType": "FunctionCall",+                        "src": "644:23:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes32",+                          "typeString": "bytes32"+                        }+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_bytes4",+                          "typeString": "bytes4"+                        },+                        {+                          "typeIdentifier": "t_bytes32",+                          "typeString": "bytes32"+                        }+                      ],+                      "id": 256,+                      "name": "E4",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 193,+                      "src": "632:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_bytes4_$_t_bytes32_$returns$__$",+                        "typeString": "function (bytes4,bytes32)"+                      }+                    },+                    "id": 263,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "632:36:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 264,+                  "nodeType": "EmitStatement",+                  "src": "627:41:1"+                }+              ]+            },+            "documentation": null,+            "id": 266,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e4",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 254,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "611:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 255,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "621:0:1"+            },+            "scope": 267,+            "src": "600:73:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          }+        ],+        "scope": 268,+        "src": "26:649:1"+      }+    ],+    "src": "0:675:1"+  },+  "legacyAST": {+    "absolutePath": "/home/akru/hsweb3test/contracts/Linearization.sol",+    "exportedSymbols": {+      "Linearization": [+        267+      ]+    },+    "id": 268,+    "nodeType": "SourceUnit",+    "nodes": [+      {+        "id": 169,+        "literals": [+          "solidity",+          "^",+          "0.4",+          ".22"+        ],+        "nodeType": "PragmaDirective",+        "src": "0:24:1"+      },+      {+        "baseContracts": [],+        "contractDependencies": [],+        "contractKind": "contract",+        "documentation": null,+        "fullyImplemented": true,+        "id": 267,+        "linearizedBaseContracts": [+          267+        ],+        "name": "Linearization",+        "nodeType": "ContractDefinition",+        "nodes": [+          {+            "anonymous": false,+            "documentation": null,+            "id": 175,+            "name": "E1",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 174,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 171,+                  "indexed": false,+                  "name": "sender",+                  "nodeType": "VariableDeclaration",+                  "scope": 175,+                  "src": "63:14:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_address",+                    "typeString": "address"+                  },+                  "typeName": {+                    "id": 170,+                    "name": "address",+                    "nodeType": "ElementaryTypeName",+                    "src": "63:7:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_address",+                      "typeString": "address"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 173,+                  "indexed": false,+                  "name": "amount",+                  "nodeType": "VariableDeclaration",+                  "scope": 175,+                  "src": "79:11:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 172,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "79:4:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "62:29:1"+            },+            "src": "54:38:1"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 181,+            "name": "E2",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 180,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 177,+                  "indexed": false,+                  "name": "tag",+                  "nodeType": "VariableDeclaration",+                  "scope": 181,+                  "src": "104:10:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_string_memory_ptr",+                    "typeString": "string"+                  },+                  "typeName": {+                    "id": 176,+                    "name": "string",+                    "nodeType": "ElementaryTypeName",+                    "src": "104:6:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_string_storage_ptr",+                      "typeString": "string"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 179,+                  "indexed": false,+                  "name": "uuid",+                  "nodeType": "VariableDeclaration",+                  "scope": 181,+                  "src": "116:11:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes4",+                    "typeString": "bytes4"+                  },+                  "typeName": {+                    "id": 178,+                    "name": "bytes4",+                    "nodeType": "ElementaryTypeName",+                    "src": "116:6:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes4",+                      "typeString": "bytes4"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "103:25:1"+            },+            "src": "95:34:1"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 187,+            "name": "E3",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 186,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 183,+                  "indexed": false,+                  "name": "txOrigin",+                  "nodeType": "VariableDeclaration",+                  "scope": 187,+                  "src": "141:16:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_address",+                    "typeString": "address"+                  },+                  "typeName": {+                    "id": 182,+                    "name": "address",+                    "nodeType": "ElementaryTypeName",+                    "src": "141:7:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_address",+                      "typeString": "address"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 185,+                  "indexed": false,+                  "name": "blockNumber",+                  "nodeType": "VariableDeclaration",+                  "scope": 187,+                  "src": "159:16:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 184,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "159:4:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "140:36:1"+            },+            "src": "132:45:1"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 193,+            "name": "E4",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 192,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 189,+                  "indexed": false,+                  "name": "sig",+                  "nodeType": "VariableDeclaration",+                  "scope": 193,+                  "src": "189:10:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes4",+                    "typeString": "bytes4"+                  },+                  "typeName": {+                    "id": 188,+                    "name": "bytes4",+                    "nodeType": "ElementaryTypeName",+                    "src": "189:6:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes4",+                      "typeString": "bytes4"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 191,+                  "indexed": false,+                  "name": "blockHash",+                  "nodeType": "VariableDeclaration",+                  "scope": 193,+                  "src": "201:17:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes32",+                    "typeString": "bytes32"+                  },+                  "typeName": {+                    "id": 190,+                    "name": "bytes32",+                    "nodeType": "ElementaryTypeName",+                    "src": "201:7:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes32",+                      "typeString": "bytes32"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "188:31:1"+            },+            "src": "180:40:1"+          },+          {+            "body": {+              "id": 207,+              "nodeType": "Block",+              "src": "246:67:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 197,+                          "name": "msg",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 381,+                          "src": "260:3:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_message",+                            "typeString": "msg"+                          }+                        },+                        "id": 198,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "sender",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "260:10:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30",+                        "id": 199,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "272:1:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        },+                        "value": "0"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        },+                        {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        }+                      ],+                      "id": 196,+                      "name": "E1",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 175,+                      "src": "257:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$",+                        "typeString": "function (address,uint256)"+                      }+                    },+                    "id": 200,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "257:17:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 201,+                  "nodeType": "EmitStatement",+                  "src": "252:22:1"+                },+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "hexValue": "68656c6c6f",+                        "id": 203,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "string",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "288:7:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        "value": "hello"+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30786465616462656566",+                        "id": 204,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "297:10:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        },+                        "value": "0xdeadbeef"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        }+                      ],+                      "id": 202,+                      "name": "E2",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 181,+                      "src": "285:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_bytes4_$returns$__$",+                        "typeString": "function (string memory,bytes4)"+                      }+                    },+                    "id": 205,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "285:23:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 206,+                  "nodeType": "EmitStatement",+                  "src": "280:28:1"+                }+              ]+            },+            "documentation": null,+            "id": 208,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e12",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 194,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "236:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 195,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "246:0:1"+            },+            "scope": 267,+            "src": "224:89:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 222,+              "nodeType": "Block",+              "src": "339:67:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "hexValue": "68656c6c6f",+                        "id": 212,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "string",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "353:7:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        "value": "hello"+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30786465616462656566",+                        "id": 213,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "362:10:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        },+                        "value": "0xdeadbeef"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        }+                      ],+                      "id": 211,+                      "name": "E2",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 181,+                      "src": "350:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_bytes4_$returns$__$",+                        "typeString": "function (string memory,bytes4)"+                      }+                    },+                    "id": 214,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "350:23:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 215,+                  "nodeType": "EmitStatement",+                  "src": "345:28:1"+                },+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 217,+                          "name": "msg",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 381,+                          "src": "387:3:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_message",+                            "typeString": "msg"+                          }+                        },+                        "id": 218,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "sender",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "387:10:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30",+                        "id": 219,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "399:1:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        },+                        "value": "0"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        },+                        {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        }+                      ],+                      "id": 216,+                      "name": "E1",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 175,+                      "src": "384:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$",+                        "typeString": "function (address,uint256)"+                      }+                    },+                    "id": 220,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "384:17:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 221,+                  "nodeType": "EmitStatement",+                  "src": "379:22:1"+                }+              ]+            },+            "documentation": null,+            "id": 223,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e21",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 209,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "329:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 210,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "339:0:1"+            },+            "scope": 267,+            "src": "317:89:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 232,+              "nodeType": "Block",+              "src": "431:33:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 227,+                          "name": "msg",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 381,+                          "src": "445:3:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_message",+                            "typeString": "msg"+                          }+                        },+                        "id": 228,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "sender",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "445:10:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30",+                        "id": 229,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "457:1:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        },+                        "value": "0"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        },+                        {+                          "typeIdentifier": "t_rational_0_by_1",+                          "typeString": "int_const 0"+                        }+                      ],+                      "id": 226,+                      "name": "E1",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 175,+                      "src": "442:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$",+                        "typeString": "function (address,uint256)"+                      }+                    },+                    "id": 230,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "442:17:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 231,+                  "nodeType": "EmitStatement",+                  "src": "437:22:1"+                }+              ]+            },+            "documentation": null,+            "id": 233,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e1",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 224,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "421:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 225,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "431:0:1"+            },+            "scope": 267,+            "src": "410:54:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 241,+              "nodeType": "Block",+              "src": "489:39:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "hexValue": "68656c6c6f",+                        "id": 237,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "string",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "503:7:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        "value": "hello"+                      },+                      {+                        "argumentTypes": null,+                        "hexValue": "30786465616462656566",+                        "id": 238,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": true,+                        "kind": "number",+                        "lValueRequested": false,+                        "nodeType": "Literal",+                        "src": "512:10:1",+                        "subdenomination": null,+                        "typeDescriptions": {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        },+                        "value": "0xdeadbeef"+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_stringliteral_1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8",+                          "typeString": "literal_string \"hello\""+                        },+                        {+                          "typeIdentifier": "t_rational_3735928559_by_1",+                          "typeString": "int_const 3735928559"+                        }+                      ],+                      "id": 236,+                      "name": "E2",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 181,+                      "src": "500:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_string_memory_ptr_$_t_bytes4_$returns$__$",+                        "typeString": "function (string memory,bytes4)"+                      }+                    },+                    "id": 239,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "500:23:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 240,+                  "nodeType": "EmitStatement",+                  "src": "495:28:1"+                }+              ]+            },+            "documentation": null,+            "id": 242,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e2",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 234,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "479:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 235,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "489:0:1"+            },+            "scope": 267,+            "src": "468:60:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 252,+              "nodeType": "Block",+              "src": "553:43:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 246,+                          "name": "tx",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 393,+                          "src": "567:2:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_transaction",+                            "typeString": "tx"+                          }+                        },+                        "id": 247,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "origin",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "567:9:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 248,+                          "name": "block",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 371,+                          "src": "578:5:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_block",+                            "typeString": "block"+                          }+                        },+                        "id": 249,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "number",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "578:12:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_address",+                          "typeString": "address"+                        },+                        {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      ],+                      "id": 245,+                      "name": "E3",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 187,+                      "src": "564:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$",+                        "typeString": "function (address,uint256)"+                      }+                    },+                    "id": 250,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "564:27:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 251,+                  "nodeType": "EmitStatement",+                  "src": "559:32:1"+                }+              ]+            },+            "documentation": null,+            "id": 253,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e3",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 243,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "543:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 244,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "553:0:1"+            },+            "scope": 267,+            "src": "532:64:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          },+          {+            "body": {+              "id": 265,+              "nodeType": "Block",+              "src": "621:52:1",+              "statements": [+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "expression": {+                          "argumentTypes": null,+                          "id": 257,+                          "name": "msg",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 381,+                          "src": "635:3:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_magic_message",+                            "typeString": "msg"+                          }+                        },+                        "id": 258,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "lValueRequested": false,+                        "memberName": "sig",+                        "nodeType": "MemberAccess",+                        "referencedDeclaration": null,+                        "src": "635:7:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes4",+                          "typeString": "bytes4"+                        }+                      },+                      {+                        "argumentTypes": null,+                        "arguments": [+                          {+                            "argumentTypes": null,+                            "expression": {+                              "argumentTypes": null,+                              "id": 260,+                              "name": "block",+                              "nodeType": "Identifier",+                              "overloadedDeclarations": [],+                              "referencedDeclaration": 371,+                              "src": "654:5:1",+                              "typeDescriptions": {+                                "typeIdentifier": "t_magic_block",+                                "typeString": "block"+                              }+                            },+                            "id": 261,+                            "isConstant": false,+                            "isLValue": false,+                            "isPure": false,+                            "lValueRequested": false,+                            "memberName": "number",+                            "nodeType": "MemberAccess",+                            "referencedDeclaration": null,+                            "src": "654:12:1",+                            "typeDescriptions": {+                              "typeIdentifier": "t_uint256",+                              "typeString": "uint256"+                            }+                          }+                        ],+                        "expression": {+                          "argumentTypes": [+                            {+                              "typeIdentifier": "t_uint256",+                              "typeString": "uint256"+                            }+                          ],+                          "id": 259,+                          "name": "blockhash",+                          "nodeType": "Identifier",+                          "overloadedDeclarations": [],+                          "referencedDeclaration": 372,+                          "src": "644:9:1",+                          "typeDescriptions": {+                            "typeIdentifier": "t_function_blockhash_view$_t_uint256_$returns$_t_bytes32_$",+                            "typeString": "function (uint256) view returns (bytes32)"+                          }+                        },+                        "id": 262,+                        "isConstant": false,+                        "isLValue": false,+                        "isPure": false,+                        "kind": "functionCall",+                        "lValueRequested": false,+                        "names": [],+                        "nodeType": "FunctionCall",+                        "src": "644:23:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_bytes32",+                          "typeString": "bytes32"+                        }+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_bytes4",+                          "typeString": "bytes4"+                        },+                        {+                          "typeIdentifier": "t_bytes32",+                          "typeString": "bytes32"+                        }+                      ],+                      "id": 256,+                      "name": "E4",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 193,+                      "src": "632:2:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_bytes4_$_t_bytes32_$returns$__$",+                        "typeString": "function (bytes4,bytes32)"+                      }+                    },+                    "id": 263,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "632:36:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 264,+                  "nodeType": "EmitStatement",+                  "src": "627:41:1"+                }+              ]+            },+            "documentation": null,+            "id": 266,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "e4",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 254,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "611:2:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 255,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "621:0:1"+            },+            "scope": 267,+            "src": "600:73:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "public"+          }+        ],+        "scope": 268,+        "src": "26:649:1"+      }+    ],+    "src": "0:675:1"+  },+  "compiler": {+    "name": "solc",+    "version": "0.4.24+commit.e67f0147.Emscripten.clang"+  },+  "networks": {},+  "schemaVersion": "2.0.1",+  "updatedAt": "2018-10-17T08:27:57.791Z"+}
+ test/contracts/Registry.json view
@@ -0,0 +1,506 @@+{+  "contractName": "Registry",+  "abi": [+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": true,+          "name": "listingHash",+          "type": "bytes32"+        }+      ],+      "name": "A",+      "type": "event"+    },+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": true,+          "name": "sender",+          "type": "address"+        },+        {+          "indexed": false,+          "name": "listingHash",+          "type": "bytes32"+        }+      ],+      "name": "B",+      "type": "event"+    },+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": false,+          "name": "dog",+          "type": "address"+        },+        {+          "indexed": false,+          "name": "cat",+          "type": "bytes32"+        }+      ],+      "name": "C",+      "type": "event"+    }+  ],+  "bytecode": "0x6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a7230582033480aa8fef567c80a4f8afd205add18d07c6a0f6991c2a4b0c2c20b8220f89b0029",+  "deployedBytecode": "0x6080604052600080fd00a165627a7a7230582033480aa8fef567c80a4f8afd205add18d07c6a0f6991c2a4b0c2c20b8220f89b0029",+  "sourceMap": "26:163:3:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26:163:3;;;;;;;",+  "deployedSourceMap": "26:163:3:-;;;;;",+  "source": "pragma solidity ^0.4.22;\n\ncontract Registry {\n\n\n    event A(bytes32 indexed listingHash);\n    event B(address indexed sender, bytes32 listingHash);\n    event C(address dog, bytes32 cat);\n\n}\n",+  "sourcePath": "/home/akru/hsweb3test/contracts/Registry.sol",+  "ast": {+    "absolutePath": "/home/akru/hsweb3test/contracts/Registry.sol",+    "exportedSymbols": {+      "Registry": [+        343+      ]+    },+    "id": 344,+    "nodeType": "SourceUnit",+    "nodes": [+      {+        "id": 326,+        "literals": [+          "solidity",+          "^",+          "0.4",+          ".22"+        ],+        "nodeType": "PragmaDirective",+        "src": "0:24:3"+      },+      {+        "baseContracts": [],+        "contractDependencies": [],+        "contractKind": "contract",+        "documentation": null,+        "fullyImplemented": true,+        "id": 343,+        "linearizedBaseContracts": [+          343+        ],+        "name": "Registry",+        "nodeType": "ContractDefinition",+        "nodes": [+          {+            "anonymous": false,+            "documentation": null,+            "id": 330,+            "name": "A",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 329,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 328,+                  "indexed": true,+                  "name": "listingHash",+                  "nodeType": "VariableDeclaration",+                  "scope": 330,+                  "src": "60:27:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes32",+                    "typeString": "bytes32"+                  },+                  "typeName": {+                    "id": 327,+                    "name": "bytes32",+                    "nodeType": "ElementaryTypeName",+                    "src": "60:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes32",+                      "typeString": "bytes32"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "59:29:3"+            },+            "src": "52:37:3"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 336,+            "name": "B",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 335,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 332,+                  "indexed": true,+                  "name": "sender",+                  "nodeType": "VariableDeclaration",+                  "scope": 336,+                  "src": "102:22:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_address",+                    "typeString": "address"+                  },+                  "typeName": {+                    "id": 331,+                    "name": "address",+                    "nodeType": "ElementaryTypeName",+                    "src": "102:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_address",+                      "typeString": "address"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 334,+                  "indexed": false,+                  "name": "listingHash",+                  "nodeType": "VariableDeclaration",+                  "scope": 336,+                  "src": "126:19:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes32",+                    "typeString": "bytes32"+                  },+                  "typeName": {+                    "id": 333,+                    "name": "bytes32",+                    "nodeType": "ElementaryTypeName",+                    "src": "126:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes32",+                      "typeString": "bytes32"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "101:45:3"+            },+            "src": "94:53:3"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 342,+            "name": "C",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 341,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 338,+                  "indexed": false,+                  "name": "dog",+                  "nodeType": "VariableDeclaration",+                  "scope": 342,+                  "src": "160:11:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_address",+                    "typeString": "address"+                  },+                  "typeName": {+                    "id": 337,+                    "name": "address",+                    "nodeType": "ElementaryTypeName",+                    "src": "160:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_address",+                      "typeString": "address"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 340,+                  "indexed": false,+                  "name": "cat",+                  "nodeType": "VariableDeclaration",+                  "scope": 342,+                  "src": "173:11:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes32",+                    "typeString": "bytes32"+                  },+                  "typeName": {+                    "id": 339,+                    "name": "bytes32",+                    "nodeType": "ElementaryTypeName",+                    "src": "173:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes32",+                      "typeString": "bytes32"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "159:26:3"+            },+            "src": "152:34:3"+          }+        ],+        "scope": 344,+        "src": "26:163:3"+      }+    ],+    "src": "0:190:3"+  },+  "legacyAST": {+    "absolutePath": "/home/akru/hsweb3test/contracts/Registry.sol",+    "exportedSymbols": {+      "Registry": [+        343+      ]+    },+    "id": 344,+    "nodeType": "SourceUnit",+    "nodes": [+      {+        "id": 326,+        "literals": [+          "solidity",+          "^",+          "0.4",+          ".22"+        ],+        "nodeType": "PragmaDirective",+        "src": "0:24:3"+      },+      {+        "baseContracts": [],+        "contractDependencies": [],+        "contractKind": "contract",+        "documentation": null,+        "fullyImplemented": true,+        "id": 343,+        "linearizedBaseContracts": [+          343+        ],+        "name": "Registry",+        "nodeType": "ContractDefinition",+        "nodes": [+          {+            "anonymous": false,+            "documentation": null,+            "id": 330,+            "name": "A",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 329,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 328,+                  "indexed": true,+                  "name": "listingHash",+                  "nodeType": "VariableDeclaration",+                  "scope": 330,+                  "src": "60:27:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes32",+                    "typeString": "bytes32"+                  },+                  "typeName": {+                    "id": 327,+                    "name": "bytes32",+                    "nodeType": "ElementaryTypeName",+                    "src": "60:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes32",+                      "typeString": "bytes32"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "59:29:3"+            },+            "src": "52:37:3"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 336,+            "name": "B",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 335,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 332,+                  "indexed": true,+                  "name": "sender",+                  "nodeType": "VariableDeclaration",+                  "scope": 336,+                  "src": "102:22:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_address",+                    "typeString": "address"+                  },+                  "typeName": {+                    "id": 331,+                    "name": "address",+                    "nodeType": "ElementaryTypeName",+                    "src": "102:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_address",+                      "typeString": "address"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 334,+                  "indexed": false,+                  "name": "listingHash",+                  "nodeType": "VariableDeclaration",+                  "scope": 336,+                  "src": "126:19:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes32",+                    "typeString": "bytes32"+                  },+                  "typeName": {+                    "id": 333,+                    "name": "bytes32",+                    "nodeType": "ElementaryTypeName",+                    "src": "126:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes32",+                      "typeString": "bytes32"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "101:45:3"+            },+            "src": "94:53:3"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 342,+            "name": "C",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 341,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 338,+                  "indexed": false,+                  "name": "dog",+                  "nodeType": "VariableDeclaration",+                  "scope": 342,+                  "src": "160:11:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_address",+                    "typeString": "address"+                  },+                  "typeName": {+                    "id": 337,+                    "name": "address",+                    "nodeType": "ElementaryTypeName",+                    "src": "160:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_address",+                      "typeString": "address"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                },+                {+                  "constant": false,+                  "id": 340,+                  "indexed": false,+                  "name": "cat",+                  "nodeType": "VariableDeclaration",+                  "scope": 342,+                  "src": "173:11:3",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_bytes32",+                    "typeString": "bytes32"+                  },+                  "typeName": {+                    "id": 339,+                    "name": "bytes32",+                    "nodeType": "ElementaryTypeName",+                    "src": "173:7:3",+                    "typeDescriptions": {+                      "typeIdentifier": "t_bytes32",+                      "typeString": "bytes32"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "159:26:3"+            },+            "src": "152:34:3"+          }+        ],+        "scope": 344,+        "src": "26:163:3"+      }+    ],+    "src": "0:190:3"+  },+  "compiler": {+    "name": "solc",+    "version": "0.4.24+commit.e67f0147.Emscripten.clang"+  },+  "networks": {},+  "schemaVersion": "2.0.1",+  "updatedAt": "2018-10-17T08:27:57.792Z"+}
+ test/contracts/SimpleStorage.json view
@@ -0,0 +1,600 @@+{+  "contractName": "SimpleStorage",+  "abi": [+    {+      "constant": true,+      "inputs": [],+      "name": "count",+      "outputs": [+        {+          "name": "",+          "type": "uint256"+        }+      ],+      "payable": false,+      "stateMutability": "view",+      "type": "function"+    },+    {+      "anonymous": false,+      "inputs": [+        {+          "indexed": false,+          "name": "_count",+          "type": "uint256"+        }+      ],+      "name": "_CountSet",+      "type": "event"+    },+    {+      "constant": false,+      "inputs": [+        {+          "name": "_count",+          "type": "uint256"+        }+      ],+      "name": "setCount",+      "outputs": [],+      "payable": false,+      "stateMutability": "nonpayable",+      "type": "function"+    }+  ],+  "bytecode": "0x608060405234801561001057600080fd5b50610113806100206000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14604e578063d14e62b8146076575b600080fd5b348015605957600080fd5b50606060a0565b6040518082815260200191505060405180910390f35b348015608157600080fd5b50609e6004803603810190808035906020019092919050505060a6565b005b60005481565b806000819055507f23420683cdbc4b73b0779e0325c497f5b72b3e8a92f3882a5a754c1b9eb734ec816040518082815260200191505060405180910390a1505600a165627a7a72305820a2e06ca2fff9366521c668d197df2b9e7164abd3974f3b0d54e6690ca00798400029",+  "deployedBytecode": "0x6080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306661abd14604e578063d14e62b8146076575b600080fd5b348015605957600080fd5b50606060a0565b6040518082815260200191505060405180910390f35b348015608157600080fd5b50609e6004803603810190808035906020019092919050505060a6565b005b60005481565b806000819055507f23420683cdbc4b73b0779e0325c497f5b72b3e8a92f3882a5a754c1b9eb734ec816040518082815260200191505060405180910390a1505600a165627a7a72305820a2e06ca2fff9366521c668d197df2b9e7164abd3974f3b0d54e6690ca00798400029",+  "sourceMap": "26:201:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26:201:1;;;;;;;",+  "deployedSourceMap": "26:201:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55:17;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55:17:1;;;;;;;;;;;;;;;;;;;;;;;122:103;;8:9:-1;5:2;;;30:1;27;20:12;5:2;122:103:1;;;;;;;;;;;;;;;;;;;;;;;;;;55:17;;;;:::o;122:103::-;180:6;172:5;:14;;;;201:17;211:6;201:17;;;;;;;;;;;;;;;;;;122:103;:::o",+  "source": "pragma solidity ^0.4.15;\n\ncontract SimpleStorage {\n    uint public count;\n    \n    event _CountSet(uint _count);\n    \n    function setCount(uint _count) external {\n        count = _count;\n        emit _CountSet(_count);\n    }\n}\n",+  "sourcePath": "/home/akru/hsweb3test/contracts/SimpleStorage.sol",+  "ast": {+    "absolutePath": "/home/akru/hsweb3test/contracts/SimpleStorage.sol",+    "exportedSymbols": {+      "SimpleStorage": [+        190+      ]+    },+    "id": 191,+    "nodeType": "SourceUnit",+    "nodes": [+      {+        "id": 169,+        "literals": [+          "solidity",+          "^",+          "0.4",+          ".15"+        ],+        "nodeType": "PragmaDirective",+        "src": "0:24:1"+      },+      {+        "baseContracts": [],+        "contractDependencies": [],+        "contractKind": "contract",+        "documentation": null,+        "fullyImplemented": true,+        "id": 190,+        "linearizedBaseContracts": [+          190+        ],+        "name": "SimpleStorage",+        "nodeType": "ContractDefinition",+        "nodes": [+          {+            "constant": false,+            "id": 171,+            "name": "count",+            "nodeType": "VariableDeclaration",+            "scope": 190,+            "src": "55:17:1",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_uint256",+              "typeString": "uint256"+            },+            "typeName": {+              "id": 170,+              "name": "uint",+              "nodeType": "ElementaryTypeName",+              "src": "55:4:1",+              "typeDescriptions": {+                "typeIdentifier": "t_uint256",+                "typeString": "uint256"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 175,+            "name": "_CountSet",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 174,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 173,+                  "indexed": false,+                  "name": "_count",+                  "nodeType": "VariableDeclaration",+                  "scope": 175,+                  "src": "99:11:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 172,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "99:4:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "98:13:1"+            },+            "src": "83:29:1"+          },+          {+            "body": {+              "id": 188,+              "nodeType": "Block",+              "src": "162:63:1",+              "statements": [+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 182,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 180,+                      "name": "count",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 171,+                      "src": "172:5:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_uint256",+                        "typeString": "uint256"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 181,+                      "name": "_count",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 177,+                      "src": "180:6:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_uint256",+                        "typeString": "uint256"+                      }+                    },+                    "src": "172:14:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "id": 183,+                  "nodeType": "ExpressionStatement",+                  "src": "172:14:1"+                },+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "id": 185,+                        "name": "_count",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 177,+                        "src": "211:6:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      ],+                      "id": 184,+                      "name": "_CountSet",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 175,+                      "src": "201:9:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$",+                        "typeString": "function (uint256)"+                      }+                    },+                    "id": 186,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "201:17:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 187,+                  "nodeType": "EmitStatement",+                  "src": "196:22:1"+                }+              ]+            },+            "documentation": null,+            "id": 189,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "setCount",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 178,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 177,+                  "name": "_count",+                  "nodeType": "VariableDeclaration",+                  "scope": 189,+                  "src": "140:11:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 176,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "140:4:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "139:13:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 179,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "162:0:1"+            },+            "scope": 190,+            "src": "122:103:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "external"+          }+        ],+        "scope": 191,+        "src": "26:201:1"+      }+    ],+    "src": "0:228:1"+  },+  "legacyAST": {+    "absolutePath": "/home/akru/hsweb3test/contracts/SimpleStorage.sol",+    "exportedSymbols": {+      "SimpleStorage": [+        190+      ]+    },+    "id": 191,+    "nodeType": "SourceUnit",+    "nodes": [+      {+        "id": 169,+        "literals": [+          "solidity",+          "^",+          "0.4",+          ".15"+        ],+        "nodeType": "PragmaDirective",+        "src": "0:24:1"+      },+      {+        "baseContracts": [],+        "contractDependencies": [],+        "contractKind": "contract",+        "documentation": null,+        "fullyImplemented": true,+        "id": 190,+        "linearizedBaseContracts": [+          190+        ],+        "name": "SimpleStorage",+        "nodeType": "ContractDefinition",+        "nodes": [+          {+            "constant": false,+            "id": 171,+            "name": "count",+            "nodeType": "VariableDeclaration",+            "scope": 190,+            "src": "55:17:1",+            "stateVariable": true,+            "storageLocation": "default",+            "typeDescriptions": {+              "typeIdentifier": "t_uint256",+              "typeString": "uint256"+            },+            "typeName": {+              "id": 170,+              "name": "uint",+              "nodeType": "ElementaryTypeName",+              "src": "55:4:1",+              "typeDescriptions": {+                "typeIdentifier": "t_uint256",+                "typeString": "uint256"+              }+            },+            "value": null,+            "visibility": "public"+          },+          {+            "anonymous": false,+            "documentation": null,+            "id": 175,+            "name": "_CountSet",+            "nodeType": "EventDefinition",+            "parameters": {+              "id": 174,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 173,+                  "indexed": false,+                  "name": "_count",+                  "nodeType": "VariableDeclaration",+                  "scope": 175,+                  "src": "99:11:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 172,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "99:4:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "98:13:1"+            },+            "src": "83:29:1"+          },+          {+            "body": {+              "id": 188,+              "nodeType": "Block",+              "src": "162:63:1",+              "statements": [+                {+                  "expression": {+                    "argumentTypes": null,+                    "id": 182,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "lValueRequested": false,+                    "leftHandSide": {+                      "argumentTypes": null,+                      "id": 180,+                      "name": "count",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 171,+                      "src": "172:5:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_uint256",+                        "typeString": "uint256"+                      }+                    },+                    "nodeType": "Assignment",+                    "operator": "=",+                    "rightHandSide": {+                      "argumentTypes": null,+                      "id": 181,+                      "name": "_count",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 177,+                      "src": "180:6:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_uint256",+                        "typeString": "uint256"+                      }+                    },+                    "src": "172:14:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "id": 183,+                  "nodeType": "ExpressionStatement",+                  "src": "172:14:1"+                },+                {+                  "eventCall": {+                    "argumentTypes": null,+                    "arguments": [+                      {+                        "argumentTypes": null,+                        "id": 185,+                        "name": "_count",+                        "nodeType": "Identifier",+                        "overloadedDeclarations": [],+                        "referencedDeclaration": 177,+                        "src": "211:6:1",+                        "typeDescriptions": {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      }+                    ],+                    "expression": {+                      "argumentTypes": [+                        {+                          "typeIdentifier": "t_uint256",+                          "typeString": "uint256"+                        }+                      ],+                      "id": 184,+                      "name": "_CountSet",+                      "nodeType": "Identifier",+                      "overloadedDeclarations": [],+                      "referencedDeclaration": 175,+                      "src": "201:9:1",+                      "typeDescriptions": {+                        "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$",+                        "typeString": "function (uint256)"+                      }+                    },+                    "id": 186,+                    "isConstant": false,+                    "isLValue": false,+                    "isPure": false,+                    "kind": "functionCall",+                    "lValueRequested": false,+                    "names": [],+                    "nodeType": "FunctionCall",+                    "src": "201:17:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_tuple$__$",+                      "typeString": "tuple()"+                    }+                  },+                  "id": 187,+                  "nodeType": "EmitStatement",+                  "src": "196:22:1"+                }+              ]+            },+            "documentation": null,+            "id": 189,+            "implemented": true,+            "isConstructor": false,+            "isDeclaredConst": false,+            "modifiers": [],+            "name": "setCount",+            "nodeType": "FunctionDefinition",+            "parameters": {+              "id": 178,+              "nodeType": "ParameterList",+              "parameters": [+                {+                  "constant": false,+                  "id": 177,+                  "name": "_count",+                  "nodeType": "VariableDeclaration",+                  "scope": 189,+                  "src": "140:11:1",+                  "stateVariable": false,+                  "storageLocation": "default",+                  "typeDescriptions": {+                    "typeIdentifier": "t_uint256",+                    "typeString": "uint256"+                  },+                  "typeName": {+                    "id": 176,+                    "name": "uint",+                    "nodeType": "ElementaryTypeName",+                    "src": "140:4:1",+                    "typeDescriptions": {+                      "typeIdentifier": "t_uint256",+                      "typeString": "uint256"+                    }+                  },+                  "value": null,+                  "visibility": "internal"+                }+              ],+              "src": "139:13:1"+            },+            "payable": false,+            "returnParameters": {+              "id": 179,+              "nodeType": "ParameterList",+              "parameters": [],+              "src": "162:0:1"+            },+            "scope": 190,+            "src": "122:103:1",+            "stateMutability": "nonpayable",+            "superFunction": null,+            "visibility": "external"+          }+        ],+        "scope": 191,+        "src": "26:201:1"+      }+    ],+    "src": "0:228:1"+  },+  "compiler": {+    "name": "solc",+    "version": "0.4.24+commit.e67f0147.Emscripten.clang"+  },+  "networks": {},+  "schemaVersion": "2.0.1",+  "updatedAt": "2018-10-17T08:28:45.992Z"+}
+ unit/Crypto/Ethereum/Test/EcdsaSpec.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE OverloadedStrings #-}+module Crypto.Ethereum.Test.EcdsaSpec where++import           Crypto.Secp256k1           (SecKey, derivePubKey)+import           Data.ByteArray             (convert)+import           Data.ByteString            (ByteString, pack)+import           Data.Serialize             (decode)+import           Test.Hspec+import           Test.Hspec.QuickCheck++import           Crypto.Ethereum+import           Data.ByteArray.HexString   (HexString)+import           Data.Solidity.Prim.Address (fromPubKey)++spec :: Spec+spec = do+    describe "Ethereum signatures" $ do+        let key = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20" :: SecKey+            address = fromPubKey (derivePubKey key)+            message = "Hello World!" :: ByteString+            sign = "0xd4a9620cd94387a31b9333935f1e76fbee8467c283d07c39c1606dc4e2af021e317293af09601dbb48f547e40f6b98fe8a67a23dcd1f7f8d054695a81521177001" :: HexString+            sign' = either error id $ decode (convert sign)++        it "sign message by Ethereum private key" $ do+            ecsign key message `shouldBe` sign'++        it "verify message by Ethereum public key" $ do+            ecrecover sign' message `shouldBe` Just address++        prop "round robin sign/verify for random message" $ \chars ->+            let msg = pack chars+             in ecrecover (ecsign key msg) msg `shouldBe` Just address
+ unit/Data/Solidity/Test/AddressSpec.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE OverloadedStrings #-}+module Data.Solidity.Test.AddressSpec where++import           Crypto.Secp256k1           (SecKey, derivePubKey)+import           Data.ByteString            (ByteString)+import           Data.ByteString.Char8      (unpack)+import           Data.Foldable              (for_)+import           Data.Monoid                ((<>))+import           Test.Hspec++import           Data.Solidity.Prim.Address++spec :: Spec+spec = do+    describe "EIP55 Test Vectors" $ for_ checksummedAddrs (\addr ->+        it (unpack addr <> " should be checksummed") $ verifyChecksum addr `shouldBe` True)++    describe "EIP55 Test Vectors Tampered" $ for_ unchecksummedAddrs (\addr ->+        it (unpack addr <> " should not be checksummed") $ verifyChecksum addr `shouldBe` False)++    describe "Conversion from/to hex string" $ do+        it "should convert from/to on valid hex" $ do+            fromHexString "0x6370eF2f4Db3611D657b90667De398a2Cc2a370C"+                `shouldBe` Right "0x6370eF2f4Db3611D657b90667De398a2Cc2a370C"++            toHexString "0x6370eF2f4Db3611D657b90667De398a2Cc2a370C"+                `shouldBe` "0x6370eF2f4Db3611D657b90667De398a2Cc2a370C"++        it "should fail on broken hex" $ do+            fromHexString "0x42"+                `shouldBe` Left "Incorrect address length: 1"+++    describe "Conversion from Secp256k1 keys" $ do+        it "derivation from private key" $ do+            let key = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20" :: SecKey+            fromPubKey (derivePubKey key)+                `shouldBe` "0x6370eF2f4Db3611D657b90667De398a2Cc2a370C"++checksummedAddrs :: [ByteString]+checksummedAddrs =+    [ "0x52908400098527886E0F7030069857D2E4169EE7"+    , "0x8617E340B3D01FA5F11F306F4090FD50E238070D"+    , "0xde709f2102306220921060314715629080e2fb77"+    , "0x27b1fdb04752bbc536007a920d24acb045561c26"+    , "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"+    , "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"+    , "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"+    , "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"+    ]++unchecksummedAddrs :: [ByteString]+unchecksummedAddrs =+    [ "0x52908400098527886E0F7030069857D2E4169Ee7"+    , "0x8617E340B3D01FA5F11F306F4090FD50E238070d"+    , "0xde709f2102306220921060314715629080e2fB77"+    , "0x27b1fdb04752bbc536007a920d24acb045561C26"+    , "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAeD"+    , "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5D359"+    , "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6Fb"+    , "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDB"+    ]
+ unit/Data/Solidity/Test/EncodingSpec.hs view
@@ -0,0 +1,265 @@+{-# LANGUAGE DataKinds         #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedLists   #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies      #-}++module Data.Solidity.Test.EncodingSpec where++import           Control.Exception          (evaluate)+import           Data.Monoid                ((<>))+import           Data.Text                  (Text)+import           Data.Tuple.OneTuple        (OneTuple (..))+import           Generics.SOP               (Generic, Rep)+import           Test.Hspec++import           Data.Solidity.Abi          (AbiGet, AbiPut, GenericAbiGet,+                                             GenericAbiPut)+import           Data.Solidity.Abi.Codec    (decode, decode', encode, encode')+import           Data.Solidity.Prim         (Address, Bytes, BytesN, IntN,+                                             ListN, UIntN)+import           Data.Solidity.Prim.Address (fromHexString, toHexString)++spec :: Spec+spec = do+  intNTest+  bytesTest+  bytesNTest+  vectorTest+  dynamicArraysTest+  tuplesTest+  addressTest++intNTest :: Spec+intNTest =+    describe "uint tests" $ do++      it "can encode int16" $+         let decoded = (-1) :: IntN 16+             encoded = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+          in roundTrip decoded encoded++      it "can encode larger uint256" $+         let decoded = (2 ^ 255) - 1 :: UIntN 256+             encoded = "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+          in roundTrip decoded encoded++bytesTest :: Spec+bytesTest = do+    describe "bytes tests" $ do++      it "can encode empty bytes" $ do+         let decoded :: Bytes+             decoded = "0x"+             encoded = "0x0000000000000000000000000000000000000000000000000000000000000000"+          in roundTrip decoded encoded++      it "can encode short bytes" $ do+         let decoded :: Bytes+             decoded = "0xc3a40000c3a4"+             encoded = "0x0000000000000000000000000000000000000000000000000000000000000006"+                    <> "0xc3a40000c3a40000000000000000000000000000000000000000000000000000"+          in roundTrip decoded encoded++      it "can encode long bytes" $ do+         let decoded :: Bytes+             decoded = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                    <> "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1"+             encoded = "0x000000000000000000000000000000000000000000000000000000000000009f"+                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                    <> "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff100"+          in roundTrip decoded encoded++bytesNTest :: Spec+bytesNTest =+    describe "sized bytes tests" $ do++      it "can encode Bytes1" $ do+         let decoded = "0xcf" :: BytesN 1+             encoded = "0xcf00000000000000000000000000000000000000000000000000000000000000"+         roundTrip decoded encoded++      it "can encode Bytes12" $ do+         let decoded = "0x6761766f66796f726b000000" :: BytesN 12+             encoded = "0x6761766f66796f726b0000000000000000000000000000000000000000000000"+         roundTrip decoded encoded++      it "can pad shorter hex-literals" $ do+         let literal = "0xc3a4" :: BytesN 4+             expected = "0xc3a40000" :: BytesN 4+         literal `shouldBe` expected++      it "can pad shorter string-literals" $ do+         let literal = "hello" :: BytesN 8+             expected = "0x68656c6c6f000000" :: BytesN 8+         literal `shouldBe` expected++      it "fails on too long literals" $ do+         let literal = "hello" :: BytesN 4+         evaluate literal `shouldThrow` errorCall "Invalid Size"++vectorTest :: Spec+vectorTest =+    describe "statically sized array tests" $ do++      it "can encode statically sized vectors of addresses" $ do+         let decoded = [False, True] :: ListN 2 Bool+             encoded = "0x0000000000000000000000000000000000000000000000000000000000000000"+                    <> "0x0000000000000000000000000000000000000000000000000000000000000001"+          in roundTrip decoded encoded++      it "can encode statically sized vectors of statically sized bytes"$  do+         let elem1 = "0xcf"+             elem2 = "0x68"+             elem3 = "0x4d"+             elem4 = "0xfb"+             decoded = [elem1, elem2, elem3, elem4] :: ListN 4 (BytesN 1)+             encoded = "0xcf00000000000000000000000000000000000000000000000000000000000000"+                    <> "0x6800000000000000000000000000000000000000000000000000000000000000"+                    <> "0x4d00000000000000000000000000000000000000000000000000000000000000"+                    <> "0xfb00000000000000000000000000000000000000000000000000000000000000"+          in roundTrip decoded encoded++dynamicArraysTest :: Spec+dynamicArraysTest = do+    describe "dynamically sized array tests" $ do++      it "can encode dynamically sized lists of bools" $ do+         let decoded = [True, True, False] :: [Bool]+             encoded = "0x0000000000000000000000000000000000000000000000000000000000000003"+                    <> "0x0000000000000000000000000000000000000000000000000000000000000001"+                    <> "0x0000000000000000000000000000000000000000000000000000000000000001"+                    <> "0x0000000000000000000000000000000000000000000000000000000000000000"+          in roundTrip decoded encoded++tuplesTest :: Spec+tuplesTest =+  describe "tuples test" $ do++    it "can encode 2-tuples with both static args" $ do+      let decoded = (True, False)+          encoded = "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000000"+       in roundTripGeneric decoded encoded++    it "can encode 1-tuples with dynamic arg" $ do+      let decoded = OneTuple ([True, False] :: [Bool])+          encoded = "0x0000000000000000000000000000000000000000000000000000000000000020"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000002"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000000"+       in roundTripGeneric decoded encoded++    it "can encode 4-tuples with a mix of args - (UInt32, String, Boolean, Array Int256)" $ do+      let decoded = (1 :: IntN 32, "dave" :: Text, True, [1, 2, 3] :: [IntN 256])+          encoded = "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000080"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0x00000000000000000000000000000000000000000000000000000000000000c0"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000004"+                 <> "0x6461766500000000000000000000000000000000000000000000000000000000"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000003"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000002"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000003"+       in roundTripGeneric decoded encoded++    it "can do something really complicated" $ do+      let uint = 1 :: UIntN 256+          int = (-1) :: IntN 256+          bool = True+          int224 = 221 :: IntN 224+          bools = [True, False] :: ListN 2 Bool+          ints = [1, -1, 3] :: [IntN 32]+          string = "hello" :: Text+          bytes16 =  "0x12345678123456781234567812345678" :: BytesN 16+          elem1 = "0x1234" :: BytesN 2+          bytes2s = [ [elem1, elem1, elem1, elem1]+                    , [elem1, elem1, elem1, elem1]+                    ] :: [ListN 4 (BytesN 2)]++          decoded = (uint, int, bool, int224, bools, ints, string, bytes16, bytes2s)++          encoded = "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0x00000000000000000000000000000000000000000000000000000000000000dd"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000000"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000140"+                 <> "0x00000000000000000000000000000000000000000000000000000000000001c0"+                 <> "0x1234567812345678123456781234567800000000000000000000000000000000"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000200"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000003"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"+                 <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000003"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000005"+                 <> "0x68656c6c6f000000000000000000000000000000000000000000000000000000"+                 <> "0x0000000000000000000000000000000000000000000000000000000000000002"+                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"+                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"+                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"+                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"+                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"+                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"+                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"+                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"++       in roundTripGeneric decoded encoded++addressTest :: Spec+addressTest =+  describe "address test" $ do+    it "can abi encode address" $ do+      let decoded = "0x4af013AfBAdb22D8A88c92D68Fc96B033b9Ebb8a" :: Address+          encoded = "0x0000000000000000000000004af013AfBAdb22D8A88c92D68Fc96B033b9Ebb8a"+       in roundTrip decoded encoded++    it "can decode address from/to bytestring" $ do+      fromHexString "0x4af013AfBAdb22D8A88c92D68Fc96B033b9Ebb8a"+        `shouldBe` Right ("0x4af013AfBAdb22D8A88c92D68Fc96B033b9Ebb8a" :: Address)++      toHexString "0x4af013AfBAdb22D8A88c92D68Fc96B033b9Ebb8a"+        `shouldBe` "0x4af013afbadb22d8a88c92d68fc96b033b9ebb8a"++    it "fails for invalid address length" $ do+      evaluate (fromHexString "0x0")+        `shouldThrow` errorCall "base16: input: invalid length"++      fromHexString "0x4af013AfBAdb22D8A88c92D68Fc96B033b9Ebb8a00"+        `shouldBe` Left "Incorrect address length: 21"++-- | Run encoded/decoded comaration+roundTrip :: ( Show a+             , Eq a+             , AbiPut a+             , AbiGet a+             )+          => a+          -> Bytes+          -> IO ()+roundTrip decoded encoded = do+  encoded `shouldBe` encode decoded+  decode encoded `shouldBe` Right decoded++-- | Run generic encoded/decoded comaration+roundTripGeneric :: ( Show a+                    , Eq a+                    , Generic a+                    , Rep a ~ rep+                    , GenericAbiPut rep+                    , GenericAbiGet rep+                    )+                 => a+                 -> Bytes+                 -> IO ()+roundTripGeneric decoded encoded = do+  encoded `shouldBe` encode' decoded+  decode' encoded `shouldBe` Right decoded
+ unit/Data/Solidity/Test/IntSpec.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE DataKinds #-}+module Data.Solidity.Test.IntSpec where++import           Test.Hspec++import           Data.Solidity.Prim.Int++spec :: Spec+spec = do+    describe "Unsigned integer overflow" $ do+        it "UIntN 256" $ do+            (negate 1 :: UIntN 256) `shouldBe` 115792089237316195423570985008687907853269984665640564039457584007913129639935+            (maxBound + 1 :: UIntN 256) `shouldBe` 0++        it "UIntN 128" $ do+            (negate 1 :: UIntN 128) `shouldBe` 340282366920938463463374607431768211455+            (maxBound + 1 :: UIntN 128) `shouldBe` 0++        it "UIntN 64" $ do+            (negate 1 :: UIntN 64) `shouldBe` 18446744073709551615+            (maxBound + 1 :: UIntN 64) `shouldBe` 0++        it "UIntN 32" $ do+            (negate 1 :: UIntN 32) `shouldBe` 4294967295+            (maxBound + 1 :: UIntN 32) `shouldBe` 0++        it "UIntN 16" $ do+            (negate 1 :: UIntN 16) `shouldBe` 65535+            (maxBound + 1 :: UIntN 16) `shouldBe` 0++        it "UIntN 8" $ do+            (negate 1 :: UIntN 8)        `shouldBe` 255+            (maxBound + 1 :: UIntN 8) `shouldBe` 0
+ unit/Language/Solidity/Test/CompilerSpec.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE OverloadedLists   #-}+{-# LANGUAGE OverloadedStrings #-}++module Language.Solidity.Test.CompilerSpec where++import           Language.Solidity.Compiler+import           Test.Hspec++spec :: Spec+spec = describe "solidity" $ do+    it "can compile empty contract" $ do+        compile (Sources [("A", "contract A {}")] [] True)+            `shouldBe` Right [("A", ("[]\n", "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a72305820613b8f0a4aab50fea86c1e4943bcddad6d753778395309a4e055efcda614b0690029"))]++    it "can handle broken contract" $ do+        compile (Sources [("Fail", "contract Fail {")] [] True)+            `shouldBe` Left "Fail:1:16: Error: Function, variable, struct or modifier declaration expected.\ncontract Fail {\n               ^\n"++    it "can compile simple contract" $ do+        compile (Sources [("SimpleStorage", "contract SimpleStorage { uint256 public a; function set(uint256 _a) { a = _a; } }")] [] True)+            `shouldBe` Right [("SimpleStorage", ("[\n\t{\n\t\t\"constant\" : true,\n\t\t\"inputs\" : [],\n\t\t\"name\" : \"a\",\n\t\t\"outputs\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"\",\n\t\t\t\t\"type\" : \"uint256\"\n\t\t\t}\n\t\t],\n\t\t\"payable\" : false,\n\t\t\"stateMutability\" : \"view\",\n\t\t\"type\" : \"function\"\n\t},\n\t{\n\t\t\"constant\" : false,\n\t\t\"inputs\" : \n\t\t[\n\t\t\t{\n\t\t\t\t\"name\" : \"_a\",\n\t\t\t\t\"type\" : \"uint256\"\n\t\t\t}\n\t\t],\n\t\t\"name\" : \"set\",\n\t\t\"outputs\" : [],\n\t\t\"payable\" : false,\n\t\t\"stateMutability\" : \"nonpayable\",\n\t\t\"type\" : \"function\"\n\t}\n]\n", "608060405234801561001057600080fd5b5060dc8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630dbe671f14604e57806360fe47b1146076575b600080fd5b348015605957600080fd5b50606060a0565b6040518082815260200191505060405180910390f35b348015608157600080fd5b50609e6004803603810190808035906020019092919050505060a6565b005b60005481565b80600081905550505600a165627a7a7230582053764f3cc73b0960abb0d97899a8133bee5eb98c131978821f7add85f33d4f2e0029"))]
− unit/Network/Ethereum/Web3/Test/EncodingSpec.hs
@@ -1,224 +0,0 @@-{-# LANGUAGE DataKinds         #-}-{-# LANGUAGE FlexibleContexts  #-}-{-# LANGUAGE OverloadedLists   #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies      #-}--module Network.Ethereum.Web3.Test.EncodingSpec where--import           Data.Monoid                      ((<>))-import           Data.Text                        (Text)-import           Generics.SOP                     (Generic, Rep)-import           Test.Hspec--import           Network.Ethereum.ABI.Class       (ABIGet, ABIPut,-                                                   GenericABIGet, GenericABIPut)-import           Network.Ethereum.ABI.Codec       (decode, decode', encode,-                                                   encode')-import           Network.Ethereum.ABI.Prim.Bool   ()-import           Network.Ethereum.ABI.Prim.Bytes  (Bytes, BytesN)-import           Network.Ethereum.ABI.Prim.Int    (IntN, UIntN)-import           Network.Ethereum.ABI.Prim.List   (ListN)-import           Network.Ethereum.ABI.Prim.String ()-import           Network.Ethereum.ABI.Prim.Tuple  (Singleton (..))--spec :: Spec-spec = do-  intNTest-  bytesTest-  bytesNTest-  vectorTest-  dynamicArraysTest-  tuplesTest--intNTest :: Spec-intNTest =-    describe "uint tests" $ do--      it "can encode int16" $-         let decoded = (-1) :: IntN 16-             encoded = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-          in roundTrip decoded encoded--      it "can encode larger uint256" $-         let decoded = (2 ^ 255) - 1 :: UIntN 256-             encoded = "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-          in roundTrip decoded encoded--bytesTest :: Spec-bytesTest = do-    describe "bytes tests" $ do--      it "can encode short bytes" $ do-         let decoded :: Bytes-             decoded = "0xc3a40000c3a4"-             encoded = "0x0000000000000000000000000000000000000000000000000000000000000006"-                    <> "0xc3a40000c3a40000000000000000000000000000000000000000000000000000"-          in roundTrip decoded encoded--      it "can encode long bytes" $ do-         let decoded :: Bytes-             decoded = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                    <> "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1"-             encoded = "0x000000000000000000000000000000000000000000000000000000000000009f"-                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                    <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                    <> "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff100"-          in roundTrip decoded encoded--bytesNTest :: Spec-bytesNTest =-    describe "sized bytes tests" $ do--      it "can encode Bytes1" $ do-         let decoded = "0xcf" :: BytesN 1-             encoded = "0xcf00000000000000000000000000000000000000000000000000000000000000"-         roundTrip decoded encoded--      it "can encode Bytes12" $ do-         let decoded = "0x6761766f66796f726b000000" :: BytesN 12-             encoded = "0x6761766f66796f726b0000000000000000000000000000000000000000000000"-         roundTrip decoded encoded--vectorTest :: Spec-vectorTest =-    describe "statically sized array tests" $ do--      it "can encode statically sized vectors of addresses" $ do-         let decoded = [False, True] :: ListN 2 Bool-             encoded = "0x0000000000000000000000000000000000000000000000000000000000000000"-                    <> "0x0000000000000000000000000000000000000000000000000000000000000001"-          in roundTrip decoded encoded--      it "can encode statically sized vectors of statically sized bytes"$  do-         let elem1 = "0xcf"-             elem2 = "0x68"-             elem3 = "0x4d"-             elem4 = "0xfb"-             decoded = [elem1, elem2, elem3, elem4] :: ListN 4 (BytesN 1)-             encoded = "0xcf00000000000000000000000000000000000000000000000000000000000000"-                    <> "0x6800000000000000000000000000000000000000000000000000000000000000"-                    <> "0x4d00000000000000000000000000000000000000000000000000000000000000"-                    <> "0xfb00000000000000000000000000000000000000000000000000000000000000"-          in roundTrip decoded encoded--dynamicArraysTest :: Spec-dynamicArraysTest = do-    describe "dynamically sized array tests" $ do--      it "can encode dynamically sized lists of bools" $ do-         let decoded = [True, True, False] :: [Bool]-             encoded = "0x0000000000000000000000000000000000000000000000000000000000000003"-                    <> "0x0000000000000000000000000000000000000000000000000000000000000001"-                    <> "0x0000000000000000000000000000000000000000000000000000000000000001"-                    <> "0x0000000000000000000000000000000000000000000000000000000000000000"-          in roundTrip decoded encoded--tuplesTest :: Spec-tuplesTest =-  describe "tuples test" $ do--    it "can encode 2-tuples with both static args" $ do-      let decoded = (True, False)-          encoded = "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000000"-       in roundTripGeneric decoded encoded--    it "can encode 1-tuples with dynamic arg" $ do-      let decoded = Singleton ([True, False] :: [Bool])-          encoded = "0x0000000000000000000000000000000000000000000000000000000000000020"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000002"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000000"-       in roundTripGeneric decoded encoded--    it "can encode 4-tuples with a mix of args - (UInt32, String, Boolean, Array Int256)" $ do-      let decoded = (1 :: IntN 32, "dave" :: Text, True, [1, 2, 3] :: [IntN 256])-          encoded = "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000080"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0x00000000000000000000000000000000000000000000000000000000000000c0"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000004"-                 <> "0x6461766500000000000000000000000000000000000000000000000000000000"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000003"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000002"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000003"-       in roundTripGeneric decoded encoded--    it "can do something really complicated" $ do-      let uint = 1 :: UIntN 256-          int = (-1) :: IntN 256-          bool = True-          int224 = 221 :: IntN 224-          bools = [True, False] :: ListN 2 Bool-          ints = [1, (-1), 3] :: [IntN 32]-          string = "hello" :: Text-          bytes16 =  "0x12345678123456781234567812345678" :: BytesN 16-          elem = "0x1234" :: BytesN 2-          bytes2s = [ [elem, elem, elem, elem]-                    , [elem, elem, elem, elem]-                    ] :: [ListN 4 (BytesN 2)]--          decoded = (uint, int, bool, int224, bools, ints, string, bytes16, bytes2s)--          encoded = "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0x00000000000000000000000000000000000000000000000000000000000000dd"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000000"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000140"-                 <> "0x00000000000000000000000000000000000000000000000000000000000001c0"-                 <> "0x1234567812345678123456781234567800000000000000000000000000000000"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000200"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000003"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000001"-                 <> "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000003"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000005"-                 <> "0x68656c6c6f000000000000000000000000000000000000000000000000000000"-                 <> "0x0000000000000000000000000000000000000000000000000000000000000002"-                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"-                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"-                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"-                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"-                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"-                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"-                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"-                 <> "0x1234000000000000000000000000000000000000000000000000000000000000"--       in roundTripGeneric decoded encoded---- | Run encoded/decoded comaration-roundTrip :: ( Show a-             , Eq a-             , ABIPut a-             , ABIGet a-             )-          => a-          -> Bytes-          -> IO ()-roundTrip decoded encoded = do-  encoded `shouldBe` encode decoded-  decode encoded `shouldBe` Right decoded---- | Run generic encoded/decoded comaration-roundTripGeneric :: ( Show a-                    , Eq a-                    , Generic a-                    , Rep a ~ rep-                    , GenericABIPut rep-                    , GenericABIGet rep-                    )-                 => a-                 -> Bytes-                 -> IO ()-roundTripGeneric decoded encoded = do-  encoded `shouldBe` encode' decoded-  decode' encoded `shouldBe` Right decoded
unit/Network/Ethereum/Web3/Test/EventSpec.hs view
@@ -5,20 +5,15 @@  module Network.Ethereum.Web3.Test.EventSpec where -import           Data.Tagged                       (Tagged)-import           Generics.SOP                      (Generic)-import qualified GHC.Generics                      as GHC (Generic)-import           Test.Hspec                        (Spec, describe, it,-                                                    shouldBe)+import           Data.Tagged                (Tagged)+import           Generics.SOP               (Generic)+import qualified GHC.Generics               as GHC (Generic)+import           Test.Hspec                 (Spec, describe, it, shouldBe) -import           Network.Ethereum.ABI.Class        (ABIGet)-import           Network.Ethereum.ABI.Event        (IndexedEvent (..),-                                                    decodeEvent)-import           Network.Ethereum.ABI.Prim.Address (Address)-import           Network.Ethereum.ABI.Prim.Bytes   ()-import           Network.Ethereum.ABI.Prim.Int     (UIntN)-import           Network.Ethereum.ABI.Prim.Tagged  ()-import           Network.Ethereum.Web3.Types       (Change (..))+import           Data.Solidity.Abi          (AbiGet, AbiType (..))+import           Data.Solidity.Event        (IndexedEvent (..), decodeEvent)+import           Data.Solidity.Prim         (Address, UIntN)+import           Network.Ethereum.Api.Types (Change (..))   spec :: Spec@@ -60,11 +55,18 @@ data NewCount = NewCount (UIntN 256) deriving (Eq, Show, GHC.Generic) instance Generic NewCount + data NewCountIndexed = NewCountIndexed  deriving (Eq, Show, GHC.Generic) instance Generic NewCountIndexed+instance AbiType NewCountIndexed where+    isDynamic = const False+instance AbiGet NewCountIndexed  data NewCountNonIndexed = NewCountNonIndexed (Tagged 1 (UIntN 256)) deriving (Eq, Show, GHC.Generic) instance Generic NewCountNonIndexed+instance AbiType NewCountNonIndexed where+    isDynamic = const False+instance AbiGet NewCountNonIndexed  instance IndexedEvent NewCountIndexed NewCountNonIndexed NewCount where   isAnonymous = const False@@ -75,9 +77,15 @@  data TransferIndexed = TransferIndexed (Tagged 1 Address) (Tagged 3 Address) deriving (Eq, Show, GHC.Generic) instance Generic TransferIndexed+instance AbiType TransferIndexed where+    isDynamic = const False+instance AbiGet TransferIndexed  data TransferNonIndexed = TransferNonIndexed (Tagged 2 (UIntN 256)) deriving (Eq, Show, GHC.Generic) instance Generic TransferNonIndexed+instance AbiType TransferNonIndexed where+    isDynamic = const False+instance AbiGet TransferNonIndexed  instance IndexedEvent TransferIndexed TransferNonIndexed Transfer where   isAnonymous = const False
+ unit/Network/Ethereum/Web3/Test/LocalAccountSpec.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE OverloadedStrings #-}++module Network.Ethereum.Web3.Test.LocalAccountSpec where++import           Crypto.Ethereum                     (SecKey)+import           Test.Hspec++import           Network.Ethereum.Account.PrivateKey (signTransaction)+import           Network.Ethereum.Api.Types          (Call (..), Quantity (..))++-- using same example as in this blog post:+-- https://medium.com/@codetractio/walkthrough-of-an-ethereum-improvement-proposal-eip-6fda3966d171+spec :: Spec+spec = describe "transaction signing" $ do+    let testCall = Call Nothing+                        (Just "0x3535353535353535353535353535353535353535")+                        (Just . Quantity $ 21000)+                        (Just . Quantity $ 20000000000)+                        (Just . Quantity $ 1000000000000000000)+                        Nothing+                        (Just 9)+        privKey = "4646464646464646464646464646464646464646464646464646464646464646" :: SecKey+        correctSignedTx = "0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83"++    it "can create valid raw transaction" $+        signTransaction testCall 1 privKey `shouldBe` correctSignedTx
unit/Network/Ethereum/Web3/Test/MethodDumpSpec.hs view
@@ -4,11 +4,10 @@  import           Network.Ethereum.Contract.TH import           Test.Hspec-import           Text.Printf   spec :: Spec spec = describe "methodDump" $     it "can dump an ABI" $  do-        let theApiDump = [abiFrom|examples/ERC20.json|]+        let theApiDump = [abiFrom|examples/token/ERC20.json|]          in theApiDump `shouldNotBe` ""
web3.cabal view
@@ -1,12 +1,13 @@-cabal-version: >=1.10+cabal-version: 1.12 name: web3-version: 0.7.3.0+version: 0.8.0.0 license: BSD3 license-file: LICENSE-copyright: Alexander Krupenkin+copyright: (c) Alexander Krupenkin 2016 maintainer: mail@akru.me author: Alexander Krupenkin homepage: https://github.com/airalab/hs-web3#readme+bug-reports: https://github.com/airalab/hs-web3/issues synopsis: Ethereum API for Haskell description:     Web3 is a Haskell client library for Ethereum@@ -15,147 +16,253 @@ extra-source-files:     README.md     CHANGELOG.md-    test-support/contracts/Migrations.sol-    test-support/contracts/SimpleStorage.sol-    test-support/truffle.js-    test-support/migrations/1_initial_migration.js-    test-support/migrations/2_deploy_contracts.js-    test-support/convertAbi.sh-    test-support/inject-contract-addresses.sh-    examples/ERC20.hs-    examples/ERC20.json-    examples/TokenInfo.hs+    stack.yaml+    examples/token/ERC20.hs+    examples/token/ERC20.json+    examples/token/Main.hs+    test/contracts/Registry.json+    test/contracts/SimpleStorage.json+    test/contracts/ComplexStorage.json+    test/contracts/Linearization.json  source-repository head     type: git     location: https://github.com/airalab/hs-web3 -flag tls+flag debug     description:-        Enable TLS support+        Enable debug compiler options     default: False+    manual: True +flag solidity+    description:+        Enable Solidity compiler+    default: False+    manual: True+ library     exposed-modules:-        Network.Ethereum.Web3-        Network.Ethereum.Web3.Eth-        Network.Ethereum.Web3.Net-        Network.Ethereum.Web3.Web3-        Network.Ethereum.Web3.Types-        Network.Ethereum.Web3.Provider-        Network.Ethereum.Unit-        Network.Ethereum.ABI.Json-        Network.Ethereum.ABI.Class-        Network.Ethereum.ABI.Codec-        Network.Ethereum.ABI.Event-        Network.Ethereum.ABI.Event.Internal-        Network.Ethereum.ABI.Generic-        Network.Ethereum.ABI.Prim-        Network.Ethereum.ABI.Prim.Int-        Network.Ethereum.ABI.Prim.Bool-        Network.Ethereum.ABI.Prim.List-        Network.Ethereum.ABI.Prim.Bytes-        Network.Ethereum.ABI.Prim.Tuple-        Network.Ethereum.ABI.Prim.Tuple.TH-        Network.Ethereum.ABI.Prim.String-        Network.Ethereum.ABI.Prim.Tagged-        Network.Ethereum.ABI.Prim.Address-        Network.Ethereum.Contract.TH+        Crypto.Ethereum+        Data.ByteArray.HexString+        Data.Solidity.Abi+        Data.Solidity.Abi.Codec+        Data.Solidity.Abi.Generic+        Data.Solidity.Event+        Data.Solidity.Event.Internal+        Data.Solidity.Prim+        Data.Solidity.Prim.Address+        Data.Solidity.Prim.Bool+        Data.Solidity.Prim.Bytes+        Data.Solidity.Prim.Int+        Data.Solidity.Prim.List+        Data.Solidity.Prim.String+        Data.Solidity.Prim.Tagged+        Data.Solidity.Prim.Tuple+        Data.Solidity.Prim.Tuple.TH+        Data.String.Extra+        Language.Solidity.Abi+        Language.Solidity.Compiler+        Language.Solidity.Compiler.Foreign+        Network.Ethereum.Account+        Network.Ethereum.Account.Class+        Network.Ethereum.Account.Default+        Network.Ethereum.Account.Internal+        Network.Ethereum.Account.Personal+        Network.Ethereum.Account.PrivateKey+        Network.Ethereum.Account.Safe+        Network.Ethereum.Api.Eth+        Network.Ethereum.Api.Net+        Network.Ethereum.Api.Personal+        Network.Ethereum.Api.Provider+        Network.Ethereum.Api.Types+        Network.Ethereum.Api.Web3+        Network.Ethereum.Chain+        Network.Ethereum.Contract         Network.Ethereum.Contract.Event+        Network.Ethereum.Contract.Event.Common+        Network.Ethereum.Contract.Event.MultiFilter+        Network.Ethereum.Contract.Event.SingleFilter         Network.Ethereum.Contract.Method+        Network.Ethereum.Contract.TH+        Network.Ethereum.Ens+        Network.Ethereum.Ens.PublicResolver+        Network.Ethereum.Ens.Registry+        Network.Ethereum.Unit+        Network.Ethereum.Web3         Network.JsonRpc.TinyClient-        Data.String.Extra     hs-source-dirs: src+    other-modules:+        Paths_web3     default-language: Haskell2010-    ghc-options: -Wduplicate-exports -Whi-shadowing -Widentities-                 -Wnoncanonical-monoid-instances -Woverlapping-patterns -Wtabs-                 -Wpartial-type-signatures -Wderiving-typeable-                 -Wunrecognised-pragmas -Wunticked-promoted-constructors-                 -Wtyped-holes -Wincomplete-patterns -Wincomplete-uni-patterns-                 -Wmissing-fields -Wmissing-methods -Wmissing-exported-signatures+    ghc-options: -funbox-strict-fields -Wduplicate-exports+                 -Whi-shadowing -Widentities -Woverlapping-patterns+                 -Wpartial-type-signatures -Wunrecognised-pragmas -Wtyped-holes+                 -Wincomplete-patterns -Wincomplete-uni-patterns -Wmissing-fields+                 -Wmissing-methods -Wmissing-exported-signatures                  -Wmissing-monadfail-instances -Wmissing-signatures -Wname-shadowing-                 -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances                  -Wunused-binds -Wunused-top-binds -Wunused-local-binds                  -Wunused-pattern-binds -Wunused-imports -Wunused-matches-                 -Wunused-foralls -Wunused-do-bind -Wwrong-do-bind-                 -Wtrustworthy-safe -Wwarnings-deprecations -Wdeferred-type-errors+                 -Wunused-foralls -Wtabs     build-depends:-        base >4.9 && <4.12,-        template-haskell >=2.12.0.0 && <2.14,+        OneTuple >=0.2.1 && <0.3,+        aeson >=1.1.2.0 && <1.5,+        async >=2.1.1.1 && <2.3,+        base >4.9 && <4.13,+        basement >=0.0.4 && <0.1,+        bytestring >=0.10.8.1 && <0.11,+        cereal >=0.5.4.0 && <0.6,+        cryptonite >=0.23 && <0.26,         data-default >=0.7.1.1 && <0.8,-        generics-sop >=0.3.2.0 && <0.4,-        transformers >=0.5.2.0 && <0.6,-        http-client >=0.5.12.1 && <0.6,         exceptions >=0.8.3 && <0.11,-        bytestring >=0.10.8.2 && <0.11,-        cryptonite ==0.25.*,-        basement >=0.0.7 && <0.1,+        generics-sop >=0.3.1.0 && <0.4,+        http-client >=0.5.7.1 && <0.6,+        http-client-tls >=0.3.5.1 && <0.4,         machines >=0.6.3 && <0.7,+        memory >=0.14.11 && <0.15,+        microlens >=0.4.8.1 && <0.5,+        microlens-aeson >=2.2.0.2 && <2.4,+        microlens-mtl >=0.1.11.0 && <0.2,+        microlens-th >=0.4.1.1 && <0.5,+        mtl >=2.2.1 && <2.3,+        parsec >=3.1.11 && <3.2,+        relapse >=1.0.0.0 && <2.0,+        secp256k1-haskell >=0.1.4 && <0.2,         tagged >=0.8.5 && <0.9,-        parsec >=3.1.13.0 && <3.2,-        memory >=0.14.16 && <0.15,-        cereal >=0.5.5.0 && <0.6,-        aeson >=1.2.4.0 && <1.4,-        async >=2.1.1.1 && <2.3,-        text >=1.2.3.0 && <1.3,-        mtl >=2.2.2 && <2.3+        template-haskell >=2.11.1.0 && <2.15,+        text >=1.2.2.2 && <1.3,+        transformers >=0.5.2.0 && <0.6,+        vinyl >=0.5.3 && <0.10     -    if flag(tls)-        cpp-options: -DTLS_MANAGER+    if flag(debug)+        ghc-options: -ddump-splices+    +    if flag(solidity)+        cpp-options: -DSOLIDITY_COMPILER+        c-sources:+            ./cbits/solidity_lite.cpp+        extra-libraries:+            solidity+        include-dirs: ./cbits         build-depends:-            http-client-tls >=0.3.5.3 && <0.4+            containers >=0.5.11.0 && <0.6 -test-suite unit+test-suite live     type: exitcode-stdio-1.0     main-is: Spec.hs-    hs-source-dirs: unit+    hs-source-dirs: test     other-modules:-        Network.Ethereum.Web3.Test.MethodDumpSpec-        Network.Ethereum.Web3.Test.EncodingSpec-        Network.Ethereum.Web3.Test.EventSpec+        Network.Ethereum.Web3.Test.ComplexStorageSpec+        Network.Ethereum.Web3.Test.ERC20Spec+        Network.Ethereum.Web3.Test.LinearizationSpec+        Network.Ethereum.Web3.Test.RegistrySpec+        Network.Ethereum.Web3.Test.SimpleStorageSpec+        Network.Ethereum.Web3.Test.Utils+        Paths_web3     default-language: Haskell2010-    ghc-options: -threaded -rtsopts -with-rtsopts=-N+    ghc-options: -funbox-strict-fields -Wduplicate-exports+                 -Whi-shadowing -Widentities -Woverlapping-patterns+                 -Wpartial-type-signatures -Wunrecognised-pragmas -Wtyped-holes+                 -Wincomplete-patterns -Wincomplete-uni-patterns -Wmissing-fields+                 -Wmissing-methods -Wmissing-exported-signatures+                 -Wmissing-monadfail-instances -Wmissing-signatures -Wname-shadowing+                 -Wunused-binds -Wunused-top-binds -Wunused-local-binds+                 -Wunused-pattern-binds -Wunused-imports -Wunused-matches+                 -Wunused-foralls -Wtabs -threaded -rtsopts -with-rtsopts=-N     build-depends:-        base >4.9 && <4.12,-        hspec-expectations >=0.8.2 && <0.9,-        hspec-discover >=2.4.8 && <2.6,-        hspec-contrib >=0.4.0 && <0.6,-        hspec >=2.4.8 && <2.6,+        OneTuple >=0.2.1 && <0.3,+        aeson >=1.1.2.0 && <1.5,+        async >=2.1.1.1 && <2.3,+        base >4.9 && <4.13,+        basement >=0.0.4 && <0.1,+        bytestring >=0.10.8.1 && <0.11,+        cereal >=0.5.4.0 && <0.6,+        cryptonite >=0.23 && <0.26,         data-default >=0.7.1.1 && <0.8,-        generics-sop >=0.3.2.0 && <0.4,-        transformers >=0.5.2.0 && <0.6,-        bytestring >=0.10.8.2 && <0.11,-        memory >=0.14.16 && <0.15,+        exceptions >=0.8.3 && <0.11,+        generics-sop >=0.3.1.0 && <0.4,+        hspec >=2.4.4 && <2.6,+        hspec-contrib >=0.4.0 && <0.6,+        hspec-discover >=2.4.4 && <2.6,+        hspec-expectations >=0.8.2 && <0.9,+        http-client >=0.5.7.1 && <0.6,+        http-client-tls >=0.3.5.1 && <0.4,+        machines >=0.6.3 && <0.7,+        memory >=0.14.11 && <0.15,+        microlens >=0.4.8.1 && <0.5,+        microlens-aeson >=2.2.0.2 && <2.4,+        microlens-mtl >=0.1.11.0 && <0.2,+        microlens-th >=0.4.1.1 && <0.5,+        mtl >=2.2.1 && <2.3,+        parsec >=3.1.11 && <3.2,+        random ==1.1.*,+        relapse >=1.0.0.0 && <2.0,+        secp256k1-haskell >=0.1.4 && <0.2,+        split >=0.2.3 && <0.3,+        stm >=2.4.4 && <2.6,         tagged >=0.8.5 && <0.9,-        split >=0.2.3.3 && <0.3,-        time >=1.8.0.2 && <1.9,-        text >=1.2.3.0 && <1.3,+        template-haskell >=2.11.1.0 && <2.15,+        text >=1.2.2.2 && <1.3,+        time >=1.6.0 && <1.9,+        transformers >=0.5.2.0 && <0.6,+        vinyl >=0.5.3 && <0.10,         web3 -any -test-suite live+test-suite unit     type: exitcode-stdio-1.0     main-is: Spec.hs-    hs-source-dirs: test+    hs-source-dirs: unit     other-modules:-        Network.Ethereum.Web3.Test.ComplexStorageSpec-        Network.Ethereum.Web3.Test.SimpleStorageSpec-        Network.Ethereum.Web3.Test.Utils+        Crypto.Ethereum.Test.EcdsaSpec+        Data.Solidity.Test.AddressSpec+        Data.Solidity.Test.EncodingSpec+        Data.Solidity.Test.IntSpec+        Language.Solidity.Test.CompilerSpec+        Network.Ethereum.Web3.Test.EventSpec+        Network.Ethereum.Web3.Test.LocalAccountSpec+        Network.Ethereum.Web3.Test.MethodDumpSpec+        Paths_web3     default-language: Haskell2010-    ghc-options: -threaded -rtsopts -with-rtsopts=-N+    ghc-options: -funbox-strict-fields -Wduplicate-exports+                 -Whi-shadowing -Widentities -Woverlapping-patterns+                 -Wpartial-type-signatures -Wunrecognised-pragmas -Wtyped-holes+                 -Wincomplete-patterns -Wincomplete-uni-patterns -Wmissing-fields+                 -Wmissing-methods -Wmissing-exported-signatures+                 -Wmissing-monadfail-instances -Wmissing-signatures -Wname-shadowing+                 -Wunused-binds -Wunused-top-binds -Wunused-local-binds+                 -Wunused-pattern-binds -Wunused-imports -Wunused-matches+                 -Wunused-foralls -Wtabs -threaded -rtsopts -with-rtsopts=-N     build-depends:-        base >4.9 && <4.12,-        hspec-expectations >=0.8.2 && <0.9,-        hspec-discover >=2.4.8 && <2.6,-        hspec-contrib >=0.4.0 && <0.6,-        hspec >=2.4.8 && <2.6,-        transformers >=0.5.2.0 && <0.6,+        OneTuple >=0.2.1 && <0.3,+        aeson >=1.1.2.0 && <1.5,+        async >=2.1.1.1 && <2.3,+        base >4.9 && <4.13,+        basement >=0.0.4 && <0.1,+        bytestring >=0.10.8.1 && <0.11,+        cereal >=0.5.4.0 && <0.6,+        cryptonite >=0.23 && <0.26,         data-default >=0.7.1.1 && <0.8,-        bytestring >=0.10.8.2 && <0.11,-        memory >=0.14.16 && <0.15,+        exceptions >=0.8.3 && <0.11,+        generics-sop >=0.3.1.0 && <0.4,+        hspec >=2.4.4 && <2.6,+        hspec-contrib >=0.4.0 && <0.6,+        hspec-discover >=2.4.4 && <2.6,+        hspec-expectations >=0.8.2 && <0.9,+        http-client >=0.5.7.1 && <0.6,+        http-client-tls >=0.3.5.1 && <0.4,+        machines >=0.6.3 && <0.7,+        memory >=0.14.11 && <0.15,+        microlens >=0.4.8.1 && <0.5,+        microlens-aeson >=2.2.0.2 && <2.4,+        microlens-mtl >=0.1.11.0 && <0.2,+        microlens-th >=0.4.1.1 && <0.5,+        mtl >=2.2.1 && <2.3,+        parsec >=3.1.11 && <3.2,+        relapse >=1.0.0.0 && <2.0,+        secp256k1-haskell >=0.1.4 && <0.2,         tagged >=0.8.5 && <0.9,-        split >=0.2.3.3 && <0.3,-        async >=2.1.1.1 && <2.3,-        time >=1.8.0.2 && <1.9,-        text >=1.2.3.0 && <1.3,-        stm >=2.4.5.0 && <2.5,+        template-haskell >=2.11.1.0 && <2.15,+        text >=1.2.2.2 && <1.3,+        transformers >=0.5.2.0 && <0.6,+        vinyl >=0.5.3 && <0.10,         web3 -any