packages feed

ethereum-analyzer-0.0.1: exec_src/DumpCodeMain.hs

{-# LANGUAGE OverloadedStrings, TemplateHaskell, FlexibleContexts
  #-}

-- | Dump all contracts.
module Main
  ( main
  ) where

import Blockchain.Jsonrpc.Client
import Blockchain.Output
import Control.Monad.Logger
import Control.Monad.Trans
import Data.Maybe
import Data.Text as T hiding (map)
import HFlags
import Numeric
import System.Directory as SD

defineFlag
  "jrpcServer"
  ("127.0.0.1" :: String)
  "Ethereum json-rpc server address."

defineFlag "jrpcPort" (8545 :: Int) "Ethereum json-rpc server port."

defineFlag "contractDir" ("contracts" :: String) "Directory for contact files."

-- https://github.com/nilcons/hflags/issues/14
return []

main :: IO ()
main = do
  s <- $initHFlags "ea-dump-contract"
  putStrLn $ "Flags: " ++ show s
  flip runLoggingT printLogMsg (dumpContracts flags_jrpcServer flags_jrpcPort)

dumpContracts :: String -> Int -> LoggingT IO ()
dumpContracts server port = do
  $logInfo "Dumping eth contracts."
  ver <- web3ClientVersion server port
  $logInfo $ T.append "version is " ver
  latest_bNum <- ethBlockNumber server port
  let parsed_bns = readHex $ Prelude.drop 2 $ T.unpack latest_bNum
  $logInfo $ T.pack $ "parsing block number: " ++ show parsed_bns
  let latest_bn = fst $ Prelude.head $ parsed_bns
  $logInfo $ T.pack $ "block number is " ++ show latest_bn
  enumerateContractAt server port latest_bn
  return ()

enumerateContractAt :: String -> Int -> Int -> LoggingT IO ()
enumerateContractAt _ _ 0 = return ()
enumerateContractAt s p bn = do
  $logInfo $ T.pack $ "processing block " ++ show bn
  transactions <- ethGetTransactionsByBlockNumber s p (T.pack $ show bn)
  -- $logInfo $ T.pack $ "transactions: " ++ show transactions
  addresses <- catMaybes <$> mapM (ethGetContractAddrByTxHash s p) transactions
  -- $logInfo $ T.pack $ "addresses: " ++ show addresses
  mapM_
    (\addr -> do
       let fpath = flags_contractDir ++ "/" ++ T.unpack addr ++ ".contract"
       fileExists <- lift $ doesFileExist fpath
       if fileExists
         then $logInfo $ T.pack $ "skipping: " ++ show addr
         else do
           textCode <- ethGetCode s p addr
           lift $ writeFile fpath $ T.unpack $ T.drop 2 textCode
     -- $logInfo $ T.append "textCode is " textCode
     )
    addresses
  -- code <- getCode server port "0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe"
  -- $logInfo $ T.pack $ "decompiled code is " ++ formatCode code
  enumerateContractAt s p (bn - 1)