diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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.
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Alexander Krupenkin (c) 2016
+Copyright Alexander Krupenkin (c) 2016-2018
 
 All rights reserved.
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -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).
diff --git a/cbits/solidity_lite.cpp b/cbits/solidity_lite.cpp
new file mode 100644
--- /dev/null
+++ b/cbits/solidity_lite.cpp
@@ -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
diff --git a/examples/ERC20.hs b/examples/ERC20.hs
deleted file mode 100644
--- a/examples/ERC20.hs
+++ /dev/null
@@ -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|]
diff --git a/examples/ERC20.json b/examples/ERC20.json
deleted file mode 100644
--- a/examples/ERC20.json
+++ /dev/null
@@ -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"}]
diff --git a/examples/TokenInfo.hs b/examples/TokenInfo.hs
deleted file mode 100644
--- a/examples/TokenInfo.hs
+++ /dev/null
@@ -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 }
diff --git a/examples/token/ERC20.hs b/examples/token/ERC20.hs
new file mode 100644
--- /dev/null
+++ b/examples/token/ERC20.hs
@@ -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|]
diff --git a/examples/token/ERC20.json b/examples/token/ERC20.json
new file mode 100644
--- /dev/null
+++ b/examples/token/ERC20.json
@@ -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"}]
diff --git a/examples/token/Main.hs b/examples/token/Main.hs
new file mode 100644
--- /dev/null
+++ b/examples/token/Main.hs
@@ -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"
diff --git a/src/Crypto/Ethereum.hs b/src/Crypto/Ethereum.hs
new file mode 100644
--- /dev/null
+++ b/src/Crypto/Ethereum.hs
@@ -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)
diff --git a/src/Data/ByteArray/HexString.hs b/src/Data/ByteArray/HexString.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ByteArray/HexString.hs
@@ -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
diff --git a/src/Data/Solidity/Abi.hs b/src/Data/Solidity/Abi.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Abi.hs
@@ -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
diff --git a/src/Data/Solidity/Abi/Codec.hs b/src/Data/Solidity/Abi/Codec.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Abi/Codec.hs
@@ -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
diff --git a/src/Data/Solidity/Abi/Generic.hs b/src/Data/Solidity/Abi/Generic.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Abi/Generic.hs
@@ -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
diff --git a/src/Data/Solidity/Event.hs b/src/Data/Solidity/Event.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Event.hs
@@ -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
diff --git a/src/Data/Solidity/Event/Internal.hs b/src/Data/Solidity/Event/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Event/Internal.hs
@@ -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
diff --git a/src/Data/Solidity/Prim.hs b/src/Data/Solidity/Prim.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim.hs
@@ -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   ()
diff --git a/src/Data/Solidity/Prim/Address.hs b/src/Data/Solidity/Prim/Address.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/Address.hs
@@ -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 >>= (==)
diff --git a/src/Data/Solidity/Prim/Bool.hs b/src/Data/Solidity/Prim/Bool.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/Bool.hs
@@ -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
diff --git a/src/Data/Solidity/Prim/Bytes.hs b/src/Data/Solidity/Prim/Bytes.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/Bytes.hs
@@ -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
diff --git a/src/Data/Solidity/Prim/Int.hs b/src/Data/Solidity/Prim/Int.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/Int.hs
@@ -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
diff --git a/src/Data/Solidity/Prim/List.hs b/src/Data/Solidity/Prim/List.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/List.hs
@@ -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
diff --git a/src/Data/Solidity/Prim/String.hs b/src/Data/Solidity/Prim/String.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/String.hs
@@ -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
diff --git a/src/Data/Solidity/Prim/Tagged.hs b/src/Data/Solidity/Prim/Tagged.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/Tagged.hs
@@ -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)
diff --git a/src/Data/Solidity/Prim/Tuple.hs b/src/Data/Solidity/Prim/Tuple.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/Tuple.hs
@@ -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])
diff --git a/src/Data/Solidity/Prim/Tuple/TH.hs b/src/Data/Solidity/Prim/Tuple/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Solidity/Prim/Tuple/TH.hs
@@ -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)) [] ]
diff --git a/src/Data/String/Extra.hs b/src/Data/String/Extra.hs
--- a/src/Data/String/Extra.hs
+++ b/src/Data/String/Extra.hs
@@ -1,6 +1,6 @@
 -- |
 -- Module      :  Data.String.Extra
--- Copyright   :  Alexander Krupenkin 2016-2018
+-- Copyright   :  Alexander Krupenkin 2016
 -- License     :  BSD3
 --
 -- Maintainer  :  mail@akru.me
diff --git a/src/Language/Solidity/Abi.hs b/src/Language/Solidity/Abi.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Solidity/Abi.hs
@@ -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"
diff --git a/src/Language/Solidity/Compiler.hs b/src/Language/Solidity/Compiler.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Solidity/Compiler.hs
@@ -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
diff --git a/src/Language/Solidity/Compiler/Foreign.hsc b/src/Language/Solidity/Compiler/Foreign.hsc
new file mode 100644
--- /dev/null
+++ b/src/Language/Solidity/Compiler/Foreign.hsc
@@ -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
diff --git a/src/Network/Ethereum/ABI/Class.hs b/src/Network/Ethereum/ABI/Class.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Class.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Codec.hs b/src/Network/Ethereum/ABI/Codec.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Codec.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Event.hs b/src/Network/Ethereum/ABI/Event.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Event.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Event/Internal.hs b/src/Network/Ethereum/ABI/Event/Internal.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Event/Internal.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Generic.hs b/src/Network/Ethereum/ABI/Generic.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Generic.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Json.hs b/src/Network/Ethereum/ABI/Json.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Json.hs
+++ /dev/null
@@ -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"
diff --git a/src/Network/Ethereum/ABI/Prim.hs b/src/Network/Ethereum/ABI/Prim.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim.hs
+++ /dev/null
@@ -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 (..))
diff --git a/src/Network/Ethereum/ABI/Prim/Address.hs b/src/Network/Ethereum/ABI/Prim/Address.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/Address.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Prim/Bool.hs b/src/Network/Ethereum/ABI/Prim/Bool.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/Bool.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Prim/Bytes.hs b/src/Network/Ethereum/ABI/Prim/Bytes.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/Bytes.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Prim/Int.hs b/src/Network/Ethereum/ABI/Prim/Int.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/Int.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Prim/List.hs b/src/Network/Ethereum/ABI/Prim/List.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/List.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Prim/String.hs b/src/Network/Ethereum/ABI/Prim/String.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/String.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/ABI/Prim/Tagged.hs b/src/Network/Ethereum/ABI/Prim/Tagged.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/Tagged.hs
+++ /dev/null
@@ -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)
diff --git a/src/Network/Ethereum/ABI/Prim/Tuple.hs b/src/Network/Ethereum/ABI/Prim/Tuple.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/Tuple.hs
+++ /dev/null
@@ -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])
diff --git a/src/Network/Ethereum/ABI/Prim/Tuple/TH.hs b/src/Network/Ethereum/ABI/Prim/Tuple/TH.hs
deleted file mode 100644
--- a/src/Network/Ethereum/ABI/Prim/Tuple/TH.hs
+++ /dev/null
@@ -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)) [] ]
diff --git a/src/Network/Ethereum/Account.hs b/src/Network/Ethereum/Account.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Account.hs
@@ -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)
diff --git a/src/Network/Ethereum/Account/Class.hs b/src/Network/Ethereum/Account/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Account/Class.hs
@@ -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
+
diff --git a/src/Network/Ethereum/Account/Default.hs b/src/Network/Ethereum/Account/Default.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Account/Default.hs
@@ -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)
diff --git a/src/Network/Ethereum/Account/Internal.hs b/src/Network/Ethereum/Account/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Account/Internal.hs
@@ -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
diff --git a/src/Network/Ethereum/Account/Personal.hs b/src/Network/Ethereum/Account/Personal.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Account/Personal.hs
@@ -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
diff --git a/src/Network/Ethereum/Account/PrivateKey.hs b/src/Network/Ethereum/Account/PrivateKey.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Account/PrivateKey.hs
@@ -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
diff --git a/src/Network/Ethereum/Account/Safe.hs b/src/Network/Ethereum/Account/Safe.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Account/Safe.hs
@@ -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
diff --git a/src/Network/Ethereum/Api/Eth.hs b/src/Network/Ethereum/Api/Eth.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Api/Eth.hs
@@ -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"
diff --git a/src/Network/Ethereum/Api/Net.hs b/src/Network/Ethereum/Api/Net.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Api/Net.hs
@@ -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"
diff --git a/src/Network/Ethereum/Api/Personal.hs b/src/Network/Ethereum/Api/Personal.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Api/Personal.hs
@@ -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"
diff --git a/src/Network/Ethereum/Api/Provider.hs b/src/Network/Ethereum/Api/Provider.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Api/Provider.hs
@@ -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
diff --git a/src/Network/Ethereum/Api/Types.hs b/src/Network/Ethereum/Api/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Api/Types.hs
@@ -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)
diff --git a/src/Network/Ethereum/Api/Web3.hs b/src/Network/Ethereum/Api/Web3.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Api/Web3.hs
@@ -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"
diff --git a/src/Network/Ethereum/Chain.hs b/src/Network/Ethereum/Chain.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Chain.hs
@@ -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
diff --git a/src/Network/Ethereum/Contract.hs b/src/Network/Ethereum/Contract.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Contract.hs
@@ -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
diff --git a/src/Network/Ethereum/Contract/Event.hs b/src/Network/Ethereum/Contract/Event.hs
--- a/src/Network/Ethereum/Contract/Event.hs
+++ b/src/Network/Ethereum/Contract/Event.hs
@@ -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
diff --git a/src/Network/Ethereum/Contract/Event/Common.hs b/src/Network/Ethereum/Contract/Event/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Contract/Event/Common.hs
@@ -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
diff --git a/src/Network/Ethereum/Contract/Event/MultiFilter.hs b/src/Network/Ethereum/Contract/Event/MultiFilter.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Contract/Event/MultiFilter.hs
@@ -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
diff --git a/src/Network/Ethereum/Contract/Event/SingleFilter.hs b/src/Network/Ethereum/Contract/Event/SingleFilter.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Contract/Event/SingleFilter.hs
@@ -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 }
diff --git a/src/Network/Ethereum/Contract/Method.hs b/src/Network/Ethereum/Contract/Method.hs
--- a/src/Network/Ethereum/Contract/Method.hs
+++ b/src/Network/Ethereum/Contract/Method.hs
@@ -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
diff --git a/src/Network/Ethereum/Contract/TH.hs b/src/Network/Ethereum/Contract/TH.hs
--- a/src/Network/Ethereum/Contract/TH.hs
+++ b/src/Network/Ethereum/Contract/TH.hs
@@ -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)
diff --git a/src/Network/Ethereum/Ens.hs b/src/Network/Ethereum/Ens.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Ens.hs
@@ -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"
diff --git a/src/Network/Ethereum/Ens/PublicResolver.hs b/src/Network/Ethereum/Ens/PublicResolver.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Ens/PublicResolver.hs
@@ -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"}]|]
diff --git a/src/Network/Ethereum/Ens/Registry.hs b/src/Network/Ethereum/Ens/Registry.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Ethereum/Ens/Registry.hs
@@ -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"}]|]
diff --git a/src/Network/Ethereum/Unit.hs b/src/Network/Ethereum/Unit.hs
--- a/src/Network/Ethereum/Unit.hs
+++ b/src/Network/Ethereum/Unit.hs
@@ -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)
diff --git a/src/Network/Ethereum/Web3.hs b/src/Network/Ethereum/Web3.hs
--- a/src/Network/Ethereum/Web3.hs
+++ b/src/Network/Ethereum/Web3.hs
@@ -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
diff --git a/src/Network/Ethereum/Web3/Eth.hs b/src/Network/Ethereum/Web3/Eth.hs
deleted file mode 100644
--- a/src/Network/Ethereum/Web3/Eth.hs
+++ /dev/null
@@ -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"
diff --git a/src/Network/Ethereum/Web3/Net.hs b/src/Network/Ethereum/Web3/Net.hs
deleted file mode 100644
--- a/src/Network/Ethereum/Web3/Net.hs
+++ /dev/null
@@ -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"
diff --git a/src/Network/Ethereum/Web3/Provider.hs b/src/Network/Ethereum/Web3/Provider.hs
deleted file mode 100644
--- a/src/Network/Ethereum/Web3/Provider.hs
+++ /dev/null
@@ -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
diff --git a/src/Network/Ethereum/Web3/Types.hs b/src/Network/Ethereum/Web3/Types.hs
deleted file mode 100644
--- a/src/Network/Ethereum/Web3/Types.hs
+++ /dev/null
@@ -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)
diff --git a/src/Network/Ethereum/Web3/Web3.hs b/src/Network/Ethereum/Web3/Web3.hs
deleted file mode 100644
--- a/src/Network/Ethereum/Web3/Web3.hs
+++ /dev/null
@@ -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"
diff --git a/src/Network/JsonRpc/TinyClient.hs b/src/Network/JsonRpc/TinyClient.hs
--- a/src/Network/JsonRpc/TinyClient.hs
+++ b/src/Network/JsonRpc/TinyClient.hs
@@ -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
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -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
diff --git a/test-support/contracts/Migrations.sol b/test-support/contracts/Migrations.sol
deleted file mode 100644
--- a/test-support/contracts/Migrations.sol
+++ /dev/null
@@ -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);
-  }
-}
diff --git a/test-support/contracts/SimpleStorage.sol b/test-support/contracts/SimpleStorage.sol
deleted file mode 100644
--- a/test-support/contracts/SimpleStorage.sol
+++ /dev/null
@@ -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);
-    }
-}
diff --git a/test-support/convertAbi.sh b/test-support/convertAbi.sh
deleted file mode 100644
--- a/test-support/convertAbi.sh
+++ /dev/null
@@ -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
-
diff --git a/test-support/inject-contract-addresses.sh b/test-support/inject-contract-addresses.sh
deleted file mode 100644
--- a/test-support/inject-contract-addresses.sh
+++ /dev/null
@@ -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
-$@
diff --git a/test-support/migrations/1_initial_migration.js b/test-support/migrations/1_initial_migration.js
deleted file mode 100644
--- a/test-support/migrations/1_initial_migration.js
+++ /dev/null
@@ -1,5 +0,0 @@
-var Migrations = artifacts.require("./Migrations.sol");
-
-module.exports = function(deployer) {
-  deployer.deploy(Migrations);
-};
diff --git a/test-support/migrations/2_deploy_contracts.js b/test-support/migrations/2_deploy_contracts.js
deleted file mode 100644
--- a/test-support/migrations/2_deploy_contracts.js
+++ /dev/null
@@ -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);
-};
diff --git a/test-support/truffle.js b/test-support/truffle.js
deleted file mode 100644
--- a/test-support/truffle.js
+++ /dev/null
@@ -1,9 +0,0 @@
-module.exports = {
-  networks: {
-    development: {
-      host: "localhost",
-      port: 8545,
-      network_id: "*" // Match any network id
-    }
-  }
-};
diff --git a/test/Network/Ethereum/Web3/Test/ComplexStorageSpec.hs b/test/Network/Ethereum/Web3/Test/ComplexStorageSpec.hs
--- a/test/Network/Ethereum/Web3/Test/ComplexStorageSpec.hs
+++ b/test/Network/Ethereum/Web3/Test/ComplexStorageSpec.hs
@@ -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)
diff --git a/test/Network/Ethereum/Web3/Test/ERC20Spec.hs b/test/Network/Ethereum/Web3/Test/ERC20Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Ethereum/Web3/Test/ERC20Spec.hs
@@ -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"
diff --git a/test/Network/Ethereum/Web3/Test/LinearizationSpec.hs b/test/Network/Ethereum/Web3/Test/LinearizationSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Ethereum/Web3/Test/LinearizationSpec.hs
@@ -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
diff --git a/test/Network/Ethereum/Web3/Test/RegistrySpec.hs b/test/Network/Ethereum/Web3/Test/RegistrySpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Network/Ethereum/Web3/Test/RegistrySpec.hs
@@ -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 ()
diff --git a/test/Network/Ethereum/Web3/Test/SimpleStorageSpec.hs b/test/Network/Ethereum/Web3/Test/SimpleStorageSpec.hs
--- a/test/Network/Ethereum/Web3/Test/SimpleStorageSpec.hs
+++ b/test/Network/Ethereum/Web3/Test/SimpleStorageSpec.hs
@@ -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)
diff --git a/test/Network/Ethereum/Web3/Test/Utils.hs b/test/Network/Ethereum/Web3/Test/Utils.hs
--- a/test/Network/Ethereum/Web3/Test/Utils.hs
+++ b/test/Network/Ethereum/Web3/Test/Utils.hs
@@ -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
diff --git a/test/contracts/ComplexStorage.json b/test/contracts/ComplexStorage.json
new file mode 100644
--- /dev/null
+++ b/test/contracts/ComplexStorage.json
@@ -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"
+}
diff --git a/test/contracts/Linearization.json b/test/contracts/Linearization.json
new file mode 100644
--- /dev/null
+++ b/test/contracts/Linearization.json
@@ -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"
+}
diff --git a/test/contracts/Registry.json b/test/contracts/Registry.json
new file mode 100644
--- /dev/null
+++ b/test/contracts/Registry.json
@@ -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"
+}
diff --git a/test/contracts/SimpleStorage.json b/test/contracts/SimpleStorage.json
new file mode 100644
--- /dev/null
+++ b/test/contracts/SimpleStorage.json
@@ -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"
+}
diff --git a/unit/Crypto/Ethereum/Test/EcdsaSpec.hs b/unit/Crypto/Ethereum/Test/EcdsaSpec.hs
new file mode 100644
--- /dev/null
+++ b/unit/Crypto/Ethereum/Test/EcdsaSpec.hs
@@ -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
diff --git a/unit/Data/Solidity/Test/AddressSpec.hs b/unit/Data/Solidity/Test/AddressSpec.hs
new file mode 100644
--- /dev/null
+++ b/unit/Data/Solidity/Test/AddressSpec.hs
@@ -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"
+    ]
diff --git a/unit/Data/Solidity/Test/EncodingSpec.hs b/unit/Data/Solidity/Test/EncodingSpec.hs
new file mode 100644
--- /dev/null
+++ b/unit/Data/Solidity/Test/EncodingSpec.hs
@@ -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
diff --git a/unit/Data/Solidity/Test/IntSpec.hs b/unit/Data/Solidity/Test/IntSpec.hs
new file mode 100644
--- /dev/null
+++ b/unit/Data/Solidity/Test/IntSpec.hs
@@ -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
diff --git a/unit/Language/Solidity/Test/CompilerSpec.hs b/unit/Language/Solidity/Test/CompilerSpec.hs
new file mode 100644
--- /dev/null
+++ b/unit/Language/Solidity/Test/CompilerSpec.hs
@@ -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"))]
diff --git a/unit/Network/Ethereum/Web3/Test/EncodingSpec.hs b/unit/Network/Ethereum/Web3/Test/EncodingSpec.hs
deleted file mode 100644
--- a/unit/Network/Ethereum/Web3/Test/EncodingSpec.hs
+++ /dev/null
@@ -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
diff --git a/unit/Network/Ethereum/Web3/Test/EventSpec.hs b/unit/Network/Ethereum/Web3/Test/EventSpec.hs
--- a/unit/Network/Ethereum/Web3/Test/EventSpec.hs
+++ b/unit/Network/Ethereum/Web3/Test/EventSpec.hs
@@ -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
diff --git a/unit/Network/Ethereum/Web3/Test/LocalAccountSpec.hs b/unit/Network/Ethereum/Web3/Test/LocalAccountSpec.hs
new file mode 100644
--- /dev/null
+++ b/unit/Network/Ethereum/Web3/Test/LocalAccountSpec.hs
@@ -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
diff --git a/unit/Network/Ethereum/Web3/Test/MethodDumpSpec.hs b/unit/Network/Ethereum/Web3/Test/MethodDumpSpec.hs
--- a/unit/Network/Ethereum/Web3/Test/MethodDumpSpec.hs
+++ b/unit/Network/Ethereum/Web3/Test/MethodDumpSpec.hs
@@ -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` ""
diff --git a/web3.cabal b/web3.cabal
--- a/web3.cabal
+++ b/web3.cabal
@@ -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
