Skip to content

Commit

Permalink
Initial implementation of gas fees management as per EIP1559 (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
akolotov authored Dec 4, 2021
1 parent f2d19f8 commit 2ec5ad6
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 15 deletions.
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,17 @@ The following environment variables may be used to configure the faucet behavior
4. `MOONS_EXT` - an address of Rinkeby-xDai ERC20-to-ERC677 mediator for MOONs tokens on the xDai side. **Default:** `0x1E0507046130c31DEb20EC2f870ad070Ff266079`.
5. `BRICKS_EXT` - an address of Rinkeby-xDai ERC20-to-ERC677 mediator for BRICKs tokens on the xDai side. **Default:** `0xf85b17E64Bc788D0CB1A8c8C87c0d74e520c2A54`.
6. `FAUCET_PRIVKEY` - a private key of an account holding xdai to reward. **No default value!**.
7. `GAS_PRICE` - the gas price (in gwei) the faucet uses for reward transactions. **Default:** `1`.
8. `GAS_LIMIT` - the gas limit the faucet uses for reward transactions. **Default:** `30000`.
9. `REWARD` - amount of xdai used as reward. **Default:** `0.005`.
10. `POLLING_INTERVAL` - amount of time (in seconds) between two subsequent cycles to discover OB transfers and send rewards. **Default:** `60`.
11. `INITIAL_START_BLOCK` - a block the first faucet's attempt to discover OB transfers starts from. **No default value!**.
12. `FINALIZATION_INTERVAL` - a number of blocks starting from the chain head to consider the chain as finalized. **Default:** `12`.
13. `JSON_DB_DIR` - a directory where the faucet service keeps its data. **No default value!**.
14. `JSON_START_BLOCK` - a name of JSON file where the last observed block is stored. **Default:** `faucet_start_block.json`.
15. `JSON_CONTRACTS` - a name of JSON file where addresses of recipient-contracts are stored. **Default:** `xdai-contracts.json`.
7. `GAS_PRICE` - the gas price (in gwei) the faucet uses for reward transactions (pre-EIP1559 transactions). `-1` means to use EIP1559 transactions. **Default:** `-1`.
8. `HISTORICAL_BASE_FEE_DEPTH` - number of recent blocks to estimate the base fee as per gas (EIP1559 related). **Default:** `20`.
9. `MAX_PRIORITY_FEE` - the priority fee per gas (in gwei) used by the faucet (EIP1559 related). **Default:** `1`.
10. `MAX_FEE_RATIO` - a coefficient to adjust the base fee per gas acquired from the historical data (EIP1559 related). **Default:** `1.3`.
11. `FEE_LIMIT` - the higher bound of max fee per gas (in gwei) which is used in order to avoid expensive transactions (EIP1559 related). **Default:** `150`.
12. `GAS_LIMIT` - the gas limit the faucet uses for reward transactions. **Default:** `30000`.
13. `REWARD` - amount of xdai used as reward. **Default:** `0.005`.
14. `POLLING_INTERVAL` - amount of time (in seconds) between two subsequent cycles to discover OB transfers and send rewards. **Default:** `60`.
15. `INITIAL_START_BLOCK` - a block the first faucet's attempt to discover OB transfers starts from. **No default value!**.
16. `FINALIZATION_INTERVAL` - a number of blocks starting from the chain head to consider the chain as finalized. **Default:** `12`.
17. `JSON_DB_DIR` - a directory where the faucet service keeps its data. **No default value!**.
18. `JSON_START_BLOCK` - a name of JSON file where the last observed block is stored. **Default:** `faucet_start_block.json`.
19. `JSON_CONTRACTS` - a name of JSON file where addresses of recipient-contracts are stored. **Default:** `xdai-contracts.json`.
20. `TEST_TO_SEND` - make a transaction to itself just after running the service. **Default:** `false`.
60 changes: 57 additions & 3 deletions bridge-faucet.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from os import getenv
from dotenv import load_dotenv
from logging import basicConfig, info, INFO
from requests import post
from statistics import median, mean

basicConfig(level=INFO)

Expand All @@ -26,7 +28,12 @@

FAUCET_PRIVKEY = getenv('FAUCET_PRIVKEY', None)

GAS_PRICE = int(getenv('GAS_PRICE', 1))
GAS_PRICE = float(getenv('GAS_PRICE', -1))
HISTORICAL_BASE_FEE_DEPTH = int(getenv('HISTORICAL_BASE_FEE_DEPTH', 20))
MAX_PRIORITY_FEE = float(getenv('MAX_PRIORITY_FEE', 1))
MAX_FEE_RATIO = float(getenv('MAX_FEE_RATIO', 1.3))
FEE_LIMIT = float(getenv('FEE_LIMIT', 150))

GAS_LIMIT = int(getenv('GAS_LIMIT', 30000))
REWARD = float(getenv('REWARD', 0.005))
POLLING_INTERVAL = getenv('POLLING_INTERVAL', 60)
Expand All @@ -38,6 +45,8 @@
JSON_DB_DIR = getenv('JSON_DB_DIR', '.')
JSON_START_BLOCK = getenv('JSON_START_BLOCK', 'faucet_start_block.json')
JSON_CONTRACTS = getenv('JSON_CONTRACTS', 'xdai-contracts.json')

TEST_TO_SEND = getenv('TEST_TO_SEND', False)

if not FAUCET_PRIVKEY:
if dotenv_read:
Expand All @@ -60,6 +69,10 @@
info(f'BRICKS_EXT = {BRICKS_EXT}')
info(f'FAUCET_PRIVKEY = ...')
info(f'GAS_PRICE = {GAS_PRICE}')
info(f'HISTORICAL_BASE_FEE_DEPTH = {HISTORICAL_BASE_FEE_DEPTH}')
info(f'MAX_PRIORITY_FEE = {MAX_PRIORITY_FEE}')
info(f'MAX_FEE_RATIO = {MAX_FEE_RATIO}')
info(f'FEE_LIMIT = {FEE_LIMIT}')
info(f'GAS_LIMIT = {GAS_LIMIT}')
info(f'REWARD = {REWARD}')
info(f'POLLING_INTERVAL = {POLLING_INTERVAL}')
Expand All @@ -68,6 +81,7 @@
info(f'JSON_DB_DIR = {JSON_DB_DIR}')
info(f'JSON_START_BLOCK = {JSON_START_BLOCK}')
info(f'JSON_CONTRACTS = {JSON_CONTRACTS}')
info(f'TEST_TO_SEND = {TEST_TO_SEND}')

# event
# TokensBridged(address token, address recipient, uint256 value, bytes32 messageId)
Expand Down Expand Up @@ -146,6 +160,8 @@

faucet = Account.privateKeyToAccount(FAUCET_PRIVKEY)

sending_tested = False

try:
with open(f'{JSON_DB_DIR}/{JSON_START_BLOCK}') as f:
tmp = load(f)
Expand Down Expand Up @@ -264,6 +280,11 @@
contracts = {}

endowing = []
if TEST_TO_SEND and not sending_tested:
endowing.append(faucet.address)
info(f'activated testmode to send a transaction')
sending_tested = True

for recipient in recipients:
if recipient in contracts:
continue
Expand All @@ -289,7 +310,36 @@
raise BaseException("Cannot get faucet balance")
info(f'faucet balance: {faucet_balance}')

if faucet_balance > len(endowing) * GAS_LIMIT * Web3.toWei(GAS_PRICE, 'gwei'):
if GAS_PRICE < 0:
try:
resp = post(XDAI_RPC,
headers = {'Content-Type': 'application/json'},
json={'method': 'eth_feeHistory',
'params': [HISTORICAL_BASE_FEE_DEPTH, "latest"],
'id':1
})
except:
raise BaseException("Cannot get historical fee data")

if resp.status_code == 200:
fee_hist = resp.json()['result']
else:
raise BaseException(f'Getting historical fee data did not succeed: {resp.status_code}, {resp.text}')

base_fee_hist = list(map(lambda h: Web3.toInt(hexstr=h), fee_hist['baseFeePerGas']))
historical_base_fee = max(median(base_fee_hist), int(mean(base_fee_hist)))
info(f'Base fee based on historical data: {Web3.fromWei(historical_base_fee, "gwei")}')

recommended_priority_fee = Web3.toWei(MAX_PRIORITY_FEE, 'gwei')

max_gas_price = min(int(historical_base_fee * MAX_FEE_RATIO) + recommended_priority_fee,
Web3.toWei(FEE_LIMIT, 'gwei'))
info(f'Suggested max fee per gas: {Web3.fromWei(max_gas_price, "gwei")}')
info(f'Suggested priority fee per gas: {Web3.fromWei(recommended_priority_fee, "gwei")}')
else:
max_gas_price = Web3.toWei(GAS_PRICE, 'gwei')

if faucet_balance > len(endowing) * GAS_LIMIT * max_gas_price:
try:
nonce = xdai_w3.eth.getTransactionCount(faucet.address)
except:
Expand All @@ -299,12 +349,16 @@
tx = {
'nonce': nonce,
'gas': GAS_LIMIT,
'gasPrice': Web3.toWei(GAS_PRICE, 'gwei'),
'data': b'Rewarded for OmniBridge transaction',
'chainId': 100,
'value': Web3.toWei(REWARD, 'ether'),
'to': recipient,
}
if GAS_PRICE < 0:
tx['maxFeePerGas'] = max_gas_price
tx['maxPriorityFeePerGas'] = recommended_priority_fee
else:
tx['gasPrice'] = max_gas_price
rawtx = faucet.signTransaction(tx)
sent_tx_hash = xdai_w3.eth.sendRawTransaction(rawtx.rawTransaction)
info(f'{recipient} rewarded by {Web3.toHex(sent_tx_hash)}')
Expand Down
8 changes: 5 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
eth-account==0.5.4
web3==5.17.0
python-dotenv==0.17.1
eth-account==0.5.6
web3==5.24.0
python-dotenv==0.17.1
requests
statistics

0 comments on commit 2ec5ad6

Please sign in to comment.