diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 9d4faec..0eb1ae3 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,12 +1,5 @@
 # These are supported funding model platforms
 
-github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
-patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-custom: # Replace with a single custom sponsorship URL
+github: [Rose2161, cryptob3auty]
+open_collective: cryptob3auty
+tidelift: npm/cryptob3auty
diff --git a/.github/workflows/Myrust.yml b/.github/workflows/Myrust.yml
new file mode 100644
index 0000000..683d404
--- /dev/null
+++ b/.github/workflows/Myrust.yml
@@ -0,0 +1,22 @@
+name: Myrust
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+env:
+  CARGO_TERM_COLOR: always
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Build
+      run: cargo build --verbose
+    - name: Run tests
+      run: cargo test --verbose
diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
new file mode 100644
index 0000000..bb8c9c2
--- /dev/null
+++ b/.github/workflows/python-publish.yml
@@ -0,0 +1,30 @@
+# This workflow will upload a Python Package using Twine when a release is created
+# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
+
+name: Upload Python Package
+
+on:
+  release:
+    types: [created]
+
+jobs:
+  deploy:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up Python
+      uses: actions/setup-python@v2
+      with:
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip
+        pip install setuptools wheel twine
+    - name: Build and publish
+      env:
+        TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
+        TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
+      run: |
+        python setup.py sdist bdist_wheel
+        twine upload dist/*
diff --git a/README.md b/README.md
index d53fd3d..200c936 100755
--- a/README.md
+++ b/README.md
@@ -36,6 +36,8 @@ Currently, only the following Etherscan.io API modules are available:
 - proxies
 - blocks
 - transactions
+- Logs
+- Gas Tracker
 
 The remaining available modules provided by Etherscan.io will be added eventually...
 
@@ -58,15 +60,11 @@ Jupyter notebooks area also included in each directory to show all examples
 
 - Package and submit to PyPI
 - Add the following modules:
-  - event logs
   - geth proxy
   - websockets
-- Add robust documentation
+- Add robust 
 - Add unit test suite
 - Add request throttling based on Etherscan's suggestions
 
-## Holla at ya' boy
 
-BTC: 16Ny72US78VEjL5GUinSAavDwARb8dXWKG
 
-ETH: 0x5E8047fc033499BD5d8C463ADb29f10f11165ed0
diff --git a/etherscan/client.py b/etherscan/client.py
index 0802433..83da7a1 100755
--- a/etherscan/client.py
+++ b/etherscan/client.py
@@ -30,6 +30,10 @@ class BadRequest(ClientException):
     """Invalid request passed"""
 
 
+class InvalidAPIKey(ClientException):
+    """Invalid API key"""
+
+
 #  Assume user puts his API key in the api_key.json
 #  file under variable name "key"
 class Client(object):
@@ -59,6 +63,11 @@ class Client(object):
     TAG = '&tag='
     BOOLEAN = '&boolean='
     INDEX = '&index='
+    FROM_BLOCK = '&fromBlock='
+    TO_BLOCK = '&toBlock='
+    TOPIC0 = '&topic0='
+    TOPIC0_1_OPR = '&topic0_1_opr='
+    TOPIC1 = '&topic1='
     API_KEY = '&apikey='
 
     url_dict = {}
@@ -86,7 +95,12 @@ def __init__(self, address, api_key=''):
             (self.TAG, ''),
             (self.BOOLEAN, ''),
             (self.INDEX, ''),
-            (self.API_KEY, api_key)])
+            (self.API_KEY, api_key),
+            (self.FROM_BLOCK, ''),
+            (self.TO_BLOCK, ''),
+            (self.TOPIC0, ''),
+            (self.TOPIC0_1_OPR, ''),
+            (self.TOPIC1, '')])
 
         # Var initialization should take place within init
         self.url = None
@@ -119,6 +133,8 @@ def connect(self):
                 status = data.get('status')
                 if status == '1' or self.check_keys_api(data):
                     return data
+                elif status == '0' and data.get('result') == "Invalid API Key":
+                    raise InvalidAPIKey(data.get('result'))
                 else:
                     raise EmptyResponse(data.get('message', 'no message'))
         raise BadRequest(
diff --git a/etherscan/gas_tracker.py b/etherscan/gas_tracker.py
new file mode 100644
index 0000000..7efc516
--- /dev/null
+++ b/etherscan/gas_tracker.py
@@ -0,0 +1,44 @@
+from .client import Client
+
+
+class GasTrackerException(Exception):
+    """Base class for exceptions in this module."""
+    pass
+
+
+class GasTracker(Client):
+    def __init__(self, api_key='YourApiKeyToken'):
+        Client.__init__(self, address='', api_key=api_key)
+        self.url_dict[self.MODULE] = 'gastracker'
+        
+    def get_estimation_of_confirmation_time(self, gas_price: str) -> str:
+        """
+        Returns the estimated time, in seconds, for a transaction to be confirmed on the blockchain.
+
+        Args:
+            gas_price (str): the price paid per unit of gas, in wei
+
+        Returns:
+            str: The result is returned in seconds.
+        """
+        self.url_dict[self.ACTION] = 'gasestimate'
+        self.url_dict[self.GAS_PRICE] = gas_price
+        self.build_url()
+        req = self.connect()
+        return req['result']
+    
+    def get_gas_oracle(self) -> dict:
+        """
+        Returns the current Safe, Proposed and Fast gas prices.
+
+        Returns:
+            dict: The gas prices are returned in Gwei.
+        """
+        self.url_dict[self.ACTION] = 'gasoracle'
+        self.build_url()
+        req = self.connect()
+        return req['result']
+    
+    def get_daily_average_gas_limit(self, start_date, end_date) -> list:
+        # TODO API Pro
+        pass
diff --git a/etherscan/logs.py b/etherscan/logs.py
new file mode 100644
index 0000000..60b448f
--- /dev/null
+++ b/etherscan/logs.py
@@ -0,0 +1,48 @@
+from .client import Client
+
+
+class LogsException(Exception):
+    """Base class for exceptions in this module."""
+    pass
+
+
+class Logs(Client):
+    """
+    The Event Log API was designed to provide an alternative to the native eth_getLogs.
+    """
+    def __init__(self, api_key='YourApiKeyToken'):
+        Client.__init__(self, address='', api_key=api_key)
+        self.url_dict[self.MODULE] = 'logs'
+    
+    def get_logs(self, from_block: str, to_block='latest', 
+                 topic0='', topic1='', topic0_1_opr='and',) -> list:
+        """
+        Get Event Logs from block number [from_block] to block [to_block] , 
+        where log address = [address], topic[0] = [topic0] 'AND' topic[1] = [topic1]
+
+        Args:
+            from_block (str): start block number
+            to_block (str, optional): end block number. Defaults to 'latest'.
+            topic0 (str, optional): Defaults to ''.
+            topic1 (str, optional): Defaults to ''.
+            topic0_1_opr (str, optional): and|or between topic0 & topic1. Defaults to 'and'.
+
+        Returns:
+            list: [description]
+        """
+        # TODO: support multi topics
+        if not topic0 and topic1:
+            raise(LogsException('can not only set topic1 while topic0 is empty'))
+        self.url_dict[self.ACTION] = 'getLogs'
+        self.url_dict[self.FROM_BLOCK] = from_block if type(
+            from_block) is str else str(from_block)
+        self.url_dict[self.TO_BLOCK] = to_block if type(
+            to_block) is str else str(to_block)
+        self.url_dict[self.TOPIC0] = topic0 if type(
+            topic0) is str else hex(topic0)
+        self.url_dict[self.TOPIC1] = topic1 if type(
+            topic1) is str else hex(topic1)
+        self.url_dict[self.TOPIC0_1_OPR] = topic0_1_opr
+        self.build_url()
+        req = self.connect()
+        return req['result']
diff --git a/setup.py b/setup.py
index a547046..bc99d9d 100755
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
 
 setuptools.setup(
     name='py_etherscan_api',
-    version='0.8.0',
+    version='0.9.0',
     packages=['examples', 'examples.stats', 'examples.tokens',
               'examples.accounts', 'examples.blocks', 'examples.transactions',  'etherscan'],
     url='https://github.com/corpetty/py-etherscan-api',
diff --git a/tests/test_accounts.py b/tests/test_accounts.py
index a5129d1..8c7ff88 100755
--- a/tests/test_accounts.py
+++ b/tests/test_accounts.py
@@ -1,8 +1,9 @@
 import unittest
+import warnings
 
 from etherscan.accounts import Account
 
-SINGLE_BALANCE = '40807178566070000000000'
+SINGLE_BALANCE = '40891626854930000000000'
 SINGLE_ACCOUNT = '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a'
 MULTI_ACCOUNT = [
     '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a',
@@ -10,15 +11,18 @@
 ]
 MULTI_BALANCE = [
     {'account': '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a',
-     'balance': '40807178566070000000000'},
+     'balance': '40891626854930000000000'},
     {'account': '0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a',
-     'balance': '40807178566070000000000'}
+     'balance': '40891626854930000000000'}
 ]
 API_KEY = 'YourAPIkey'
 
 
 class AccountsTestCase(unittest.TestCase):
 
+    def setUp(self):
+        warnings.simplefilter('ignore', ResourceWarning)
+
     def test_get_balance(self):
         api = Account(address=SINGLE_ACCOUNT, api_key=API_KEY)
         self.assertEqual(api.get_balance(), SINGLE_BALANCE)
diff --git a/tests/test_blocks.py b/tests/test_blocks.py
index e3d59ff..0bdae81 100644
--- a/tests/test_blocks.py
+++ b/tests/test_blocks.py
@@ -1,4 +1,5 @@
 import unittest
+import warnings
 
 from etherscan.blocks import Blocks
 
@@ -10,6 +11,9 @@
 
 class BlocksTestCase(unittest.TestCase):
 
+    def setUp(self):
+        warnings.simplefilter('ignore', ResourceWarning)
+
     def test_get_block_reward(self):
         api = Blocks(api_key=(API_KEY))
         reward_object = api.get_block_reward(BLOCK)
diff --git a/tests/test_gas_tracker.py b/tests/test_gas_tracker.py
new file mode 100644
index 0000000..37d2303
--- /dev/null
+++ b/tests/test_gas_tracker.py
@@ -0,0 +1,27 @@
+import unittest
+import warnings
+
+from etherscan.gas_tracker import GasTracker
+
+GAS_PRICE = '2000000000'
+PRICE_ORACLE_RESULT_DICT_KEYS = ("SafeGasPrice",
+                                 "ProposeGasPrice",
+                                 "FastGasPrice",
+                                 "suggestBaseFee")
+API_KEY = 'YourAPIkey'
+
+
+class BlocksTestCase(unittest.TestCase):
+
+    def setUp(self):
+        warnings.simplefilter('ignore', ResourceWarning)
+        self.api = GasTracker(api_key=API_KEY)
+
+    def test_get_estimation_of_confirmation_time(self):
+        estimated_time = self.api.get_estimation_of_confirmation_time(GAS_PRICE)
+        self.assertTrue(int(estimated_time) > 0)
+    
+    def test_get_gas_oracle(self):
+        oracle_price = self.api.get_gas_oracle()
+        for key in PRICE_ORACLE_RESULT_DICT_KEYS:
+            self.assertTrue(key in oracle_price and float(oracle_price[key]) > 0)
diff --git a/tests/test_logs.py b/tests/test_logs.py
new file mode 100644
index 0000000..f4d36d9
--- /dev/null
+++ b/tests/test_logs.py
@@ -0,0 +1,40 @@
+import unittest
+import warnings
+
+from etherscan.logs import Logs, LogsException
+from etherscan.client import InvalidAPIKey
+
+FROM_BLOCK = 379224
+TO_BLOCK = 400000
+ADDRESS = '0x33990122638b9132ca29c723bdf037f1a891a70c'
+TOPIC0 = '0xf63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a8545'
+TOPIC1 = '0x72657075746174696f6e00000000000000000000000000000000000000000000'
+TOPIC0_1_OPR = 'and'
+API_KEY = 'YourAPIkey'
+
+
+class BlocksTestCase(unittest.TestCase):
+
+    def setUp(self):
+        warnings.simplefilter('ignore', ResourceWarning)
+        self.api = Logs(api_key=(API_KEY))
+        
+    def test_invalid_api_key(self):
+        with self.assertRaises(InvalidAPIKey):
+            api = Logs(api_key=('invalid' + API_KEY))
+            api.get_logs(from_block=FROM_BLOCK, topic0=TOPIC0)
+
+    def test_get_logs_error(self):
+        with self.assertRaises(LogsException):
+            self.api.get_logs(from_block=FROM_BLOCK, topic1=TOPIC1)
+
+    def test_get_logs_one_topic(self):
+        topics = self.api.get_logs(from_block=FROM_BLOCK, topic0=TOPIC0)
+        for topic in topics:
+            self.assertTrue(TOPIC0 in topic.get('topics', ''))
+        
+    def test_get_logs_two_topics(self):
+        topics = self.api.get_logs(from_block=FROM_BLOCK, topic0=TOPIC0, topic1=TOPIC1)
+        for topic in topics:
+            self.assertTrue(TOPIC0 in topic.get('topics', '') 
+                            and TOPIC1 in topic.get('topics', ''))
diff --git a/tests/test_proxies.py b/tests/test_proxies.py
index 9bc5e64..5067be0 100755
--- a/tests/test_proxies.py
+++ b/tests/test_proxies.py
@@ -1,5 +1,6 @@
 import re
 import unittest
+import warnings
 
 from etherscan.proxies import Proxies
 
@@ -23,11 +24,14 @@
 
 class ProxiesTestCase(unittest.TestCase):
 
+    def setUp(self):
+        warnings.simplefilter('ignore', ResourceWarning)
+
     def test_get_most_recent_block(self):
         api = Proxies(api_key=API_KEY)
         most_recent = int(api.get_most_recent_block(), 16)
         print(most_recent)
-        p = re.compile('^[0-9]{7}$')
+        p = re.compile('^[0-9]{8}$')
         self.assertTrue(p.match(str(most_recent)))
 
     def test_get_block_by_number(self):
diff --git a/tests/test_token.py b/tests/test_token.py
index fd1860e..2ce91ac 100755
--- a/tests/test_token.py
+++ b/tests/test_token.py
@@ -1,4 +1,5 @@
 import unittest
+import warnings
 
 from etherscan.tokens import Tokens
 
@@ -11,6 +12,9 @@
 
 class TokensTestCase(unittest.TestCase):
 
+    def setUp(self):
+        warnings.simplefilter('ignore', ResourceWarning)
+
     def test_get_token_supply(self):
         api = Tokens(contract_address=CONTRACT_ADDRESS, api_key=(API_KEY))
         self.assertEqual(api.get_total_supply(), ELCOIN_TOKEN_SUPPLY)
diff --git a/tests/test_transactions.py b/tests/test_transactions.py
index 7dec60c..e2847e2 100644
--- a/tests/test_transactions.py
+++ b/tests/test_transactions.py
@@ -1,4 +1,5 @@
 import unittest
+import warnings
 
 from etherscan.transactions import Transactions
 
@@ -10,6 +11,9 @@
 
 class TransactionsTestCase(unittest.TestCase):
 
+    def setUp(self):
+        warnings.simplefilter('ignore', ResourceWarning)
+
     def test_get_status(self):
         api = Transactions(api_key=(API_KEY))
         status = api.get_status(TX_1)