diff --git a/bin/libbfa/README.md b/bin/libbfa/README.md
index e5ccf3b28317b36d6e641d9deb80f2f7a45d3b9a..3d2ab36d0849c0e61599d6218897a9c3290ede76 100755
--- a/bin/libbfa/README.md
+++ b/bin/libbfa/README.md
@@ -126,3 +126,10 @@ print(majorcontr.functions.councilLength.call())
 # Fix
 print(majorcontr.functions.councilLength().call())
 ```
+
+<a name="argument-after-asterisk-must-be-an-iterable-not-nonetype"></a>
+gas required exceeds allowance
+```python
+# Error text: ValueError: {'code': -32000, 'message': 'gas required exceeds allowance (8000000)'}
+```
+Tu transacción va a fallar.
diff --git a/bin/libbfa/__init__.py b/bin/libbfa/__init__.py
index e22c7f41188f07df10965869913ebb2fcf5b1426..c06f92c2d725b6c84a540aeb94232cf88861aa67 100755
--- a/bin/libbfa/__init__.py
+++ b/bin/libbfa/__init__.py
@@ -8,6 +8,7 @@ import web3.exceptions
 import web3.middleware
 import ecdsa
 from Crypto.Hash import keccak
+import eth_account;
 
 
 class Bfa:
@@ -19,9 +20,9 @@ class Bfa:
             elif 'HOME' in os.environ and os.path.isdir(os.path.join(os.environ['HOME'], 'bfa')):
                 os.putenv('BFAHOME', os.path.join(os.environ['HOME'], 'bfa'))
         if isinstance(provider, str):
-            if provider in ['prod', 'bfa2018' 'network']:
+            if provider in ['prod', 'bfa2018', 'network', '']:
                 provider = web3.HTTPProvider("http://public.bfa.ar:8545/")
-            elif provider in ['test2network', 'test2', 'test', '']:
+            elif provider in ['test2network', 'test2', 'test']:
                 provider = web3.HTTPProvider("http://public.test2.bfa.ar:8545/")
             elif provider.startswith('http://') or provider.startswith('https://'):
                 provider = web3.HTTPProvider(provider)
@@ -35,20 +36,64 @@ class Bfa:
 
 class Account:
 
-    def __init__(self, accountname: str, passphrase: str = ''):
+    def __init__(self, *args):
+        if len(args) == 0:
+            self.new()
+            return
+        accountname = None
+        passphrase = ''
+        if len(args) >= 1:
+            accountname = args[0]
+        if len(args) >= 2:
+            passphrase = args[1]
         self.keyfile = None
-        self.privatekey = None
+        self.key = None
         self.unlock(accountname, passphrase)
         self.nonce = 0
 
     def __repr__(self) -> str:
-        return str(dict(keyfile=self.keyfile, privatekey=str(self.privatekey)))
+        return str(dict(keyfile=self.keyfile, key=str(self.key)))
 
     def __str__(self) -> str:
-        return self.walletaddress()
+        return self.address
+
+    def new(self):
+        acct = eth_account.Account.create()
+        self.address = acct.address
+        self.key = acct.key
+        self.save()
+        # print(acct.address)
+        # print(acct.key.hex())
+        return acct
+
+    def save(self):
+        dir = None
+        if os.getenv('BFANODEDIR') and os.path.exists(os.path.join(os.environ['BFANODEDIR'], 'keystore')):
+            dir = os.path.join(os.environ['BFANODEDIR'], 'keystore')
+        elif os.getenv('BFANETWORKDIR') and os.path.exists(os.path.join(os.environ['BFANETWORKDIR'], 'node', 'keystore')):
+            dir = os.path.join(os.environ['BFANETWORKDIR'], 'node', 'keystore')
+        elif os.getenv('BFAHOME') and os.path.exists(os.path.join(os.environ['BFAHOME'], 'network', 'node', 'keystore')):
+            dir = os.path.join(os.environ['BFAHOME'], 'network', 'node', 'keystore')
+        elif os.getenv('HOME'):
+            dir = os.path.join(os.environ['HOME'], '.ethereum', 'keystore')
+            os.makedirs(dir, mode=0o700, exist_ok=True)
+        else:
+            raise OSError('I have no idea where to save the file.')
+        self.keyfile = os.path.join(dir, self.address)
+        encrypted = eth_account.Account.encrypt(self.key.hex(), '')
+        try:
+            with open(self.keyfile, 'w', encoding='utf=8') as outfile:
+                outfile.write(str(encrypted).replace("'", '"'))
+        except:
+            # os.remove(filename)
+            raise
+        pass
 
     @staticmethod
-    def findkeyfilesindirectories(pattern: str):
+    def findkeyfilesindirectories(**kwargs):
+        pattern = ''
+        if 'pattern' in kwargs:
+            pattern = kwargs['pattern']
         # Remove leading 0x if present
         if pattern.startswith('0x'):
             pattern = pattern[2:]
@@ -61,7 +106,7 @@ class Account:
         elif os.getenv('BFANETWORKDIR'):
             wheretolook += [os.path.join(os.environ['BFANETWORKDIR'], 'node', 'keystore')]
         elif os.getenv('BFAHOME'):
-            wheretolook += [os.path.join(os.environ['BFANETWORKDIR'], 'network', 'node', 'keystore')]
+            wheretolook += [os.path.join(os.environ['BFAHOME'], 'network', 'node', 'keystore')]
         if os.getenv('HOME'):
             wheretolook += [
                 os.path.join(os.environ['HOME'], '.ethereum', 'keystore'),
@@ -95,35 +140,33 @@ class Account:
         if os.path.isfile(accountname):
             self.keyfile = accountname
         else:
-            self.keyfile = self.findkeyfilesindirectories(accountname)
+            self.keyfile = self.findkeyfilesindirectories(pattern=accountname)
         if self.keyfile is None:
             raise FileNotFoundError('The account was not found.')
         with open(self.keyfile) as fd:
             encrypted_key = fd.read()
             try:
-                self.privatekey = web3.Web3().eth.account.decrypt(encrypted_key, passphrase)
+                self.key = web3.Web3().eth.account.decrypt(encrypted_key, passphrase)
             except ValueError as exc:
                 raise ValueError(
-                    'The passphrase given for the account is incorrect, '
-                    'or the input file is not a valid key file.'
+                    'The passphrase given for the account in file {} is incorrect, '
+                    'or the input file is not a valid key file.'.format(self.keyfile)
                 ) from exc
-
-    def publickey(self) -> bytearray:
-        key = ecdsa.SigningKey.from_string(self.privatekey, curve=ecdsa.SECP256k1).verifying_key
-        # returns bytestring
-        return key.to_string()
-
-    def walletaddress(self) -> str:
+        # ADDRESS
+        publickey = ecdsa.SigningKey.from_string(self.key, curve=ecdsa.SECP256k1).verifying_key
+        pkbytestring = publickey.to_string() # returns bytestring
         ourhash = keccak.new(digest_bits=256)
-        ourhash.update(self.publickey())
+        ourhash.update(pkbytestring)
         digest = ourhash.hexdigest()
-        return web3.Web3().toChecksumAddress('0x' + digest[-40:])
+        self.address = web3.Web3().toChecksumAddress('0x' + digest[-40:])
 
     def transact(self, *args, **kwargs):
         w3 = kwargs.get('web3')
+        tx_details = self.calculate_tx_details(w3, *args, **kwargs)
         afunction = kwargs.get('function')
-        tx_details = self.calculate_tx_details(w3, afunction, *args)
-        txobj = afunction(*args).buildTransaction(tx_details)
+        txobj = tx_details
+        if afunction:
+            txobj = afunction(*args).buildTransaction(tx_details)
         receipt = self.txsignsendwait(w3, txobj)
         return receipt
 
@@ -135,38 +178,53 @@ class Account:
         return receipt
 
     def signtx(self, tx: dict):
-        signed = web3.Web3().eth.account.sign_transaction(tx, self.privatekey)
+        signed = web3.Web3().eth.account.sign_transaction(tx, self.key)
         return signed
 
-    def calculate_tx_details(self, w3: web3.Web3, afunction, *args) -> dict:
+    # if kwargs has extragas=50000 then we add that number to the amount
+    # of gas for the transaction
+    def calculate_tx_details(self, w3: web3.Web3, *args, **kwargs) -> dict:
         # Nonce may have increase on the network without us noticing
         # or past transactions may not yet have been mined (and a flooded
         # txpool).
         # This is a resonable fix (try not to send too many transactions)
         # If you use waitForTransactionReceipt() between each transaction
         # you will not have problems because of this.
-        self.nonce = max(self.nonce, w3.eth.getTransactionCount(self.walletaddress()))
+        afunction = kwargs.get('function')
+        self.nonce = max(self.nonce, w3.eth.getTransactionCount(self.address))
         # Set minimum gasPrice to 1 Gwei, but allow more if the network says so.
         details = {
             'chainId': w3.eth.chain_id(),
             'gasPrice': min(w3.toWei('1', 'gwei'), w3.eth.gasPrice),
             'nonce': self.nonce,
-            'from': self.walletaddress(),
+            'from': self.address,
         }
+        for kw in [ 'to', 'value' ]:
+            val = kwargs.get(kw)
+            if val is not None:
+                details[kw] = val
         # Ask for balance, so we can tell it, in case we have an exception
-        balance = w3.eth.getBalance(self.walletaddress())
+        balance = w3.eth.getBalance(self.address)
         try:
-            # Ask a node how much gas it would cost to deploy
-            gas = afunction(*args).estimateGas(details)
+            if afunction:
+                # Ask a node how much gas it would cost to deploy
+                gas = afunction(*args).estimateGas(details)
+            else:
+                gas = w3.eth.estimateGas(details)
         except web3.exceptions.SolidityError as exc:
             raise web3.exceptions.SolidityError(
                 'The Ethereum Virtual Machine probably did not like that.'
             ) from exc
         except ValueError as exc:
             raise ValueError(
-                'Your account may not have enough balance to work on this '
-                'network. It currently has {} wei.'
+                'Your transaction will fail. Maybe you are calling your '
+                'contract wrong or are not allowed to call the funcion '
+                'by a function modifier or '
+                'your account may not have enough balance to work on this '
+                'network. Your account balance is currently {} wei.'
                 .format(balance)) from exc
+        if kwargs.get('extragas') is not None:
+            gas += kwargs.get('extragas')
         details['gas'] = gas
         return details
 
@@ -258,9 +316,11 @@ class CompiledContract:
         with open('{}.sol'.format(self.name), 'r') as infile:
             with open('contract.sol', 'w') as outfile:
                 outfile.write(infile.read())
-        solc = subprocess.run(self.dockerargs(), stdout=subprocess.PIPE, check=True)
-        # Don't leave too much mess.
-        os.remove('contract.sol')
+        try:
+            solc = subprocess.run(self.dockerargs(), stdout=subprocess.PIPE, check=True)
+        finally:
+            # Don't leave too much mess.
+            os.remove('contract.sol')
         txt = solc.stdout
         output = txt.decode('utf-8')
         self.json = json.loads(output)
@@ -273,7 +333,7 @@ class CompiledContract:
         except FileNotFoundError:
             return
         if len(output) < 2:
-            print("The JSON file is too little ({} bytes read from {}).".format(len(output), filename), file=sys.stderr)
+            print("The JSON file is too small ({} bytes read from {}).".format(len(output), filename), file=sys.stderr)
             raise NameError
         try:
             self.json = json.loads(output)