diff --git a/deployment/group_vars/dai.yml b/deployment/group_vars/dai.yml index d0671110..0d7d3b3a 100644 --- a/deployment/group_vars/dai.yml +++ b/deployment/group_vars/dai.yml @@ -29,6 +29,7 @@ FOREIGN_GAS_PRICE_ORACLE_URL: "https://gasprice.poa.network/" FOREIGN_GAS_PRICE_SPEED_TYPE: "standard" FOREIGN_GAS_PRICE_FALLBACK: 10000000000 FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000 +FOREIGN_GAS_PRICE_FACTOR: 1 ## UI UI_TITLE: "TokenBridge UI app - %c" @@ -45,7 +46,9 @@ UI_FOREIGN_GAS_PRICE_FALLBACK: 10000000000 MONITOR_PORT: 3003 MONITOR_HOME_DEPLOYMENT_BLOCK: 759 MONITOR_FOREIGN_DEPLOYMENT_BLOCK: 6478417 -MONITOR_GAS_LIMIT: 300000 -MONITOR_GAS_PRICE_FALLBACK: 21 +MONITOR_HOME_GAS_LIMIT: 300000 +MONITOR_FOREIGN_GAS_LIMIT: 300000 +MONITOR_HOME_GAS_PRICE_FALLBACK: 0 +MONITOR_FOREIGN_GAS_PRICE_FALLBACK: 10000000000 MONITOR_LEFT_TX_THRESHOLD: 100 MONITOR_CRON_SCHEDULE: "* * * * *" diff --git a/deployment/group_vars/example.yml b/deployment/group_vars/example.yml index 0c9511b4..e32b0211 100644 --- a/deployment/group_vars/example.yml +++ b/deployment/group_vars/example.yml @@ -23,12 +23,14 @@ HOME_GAS_PRICE_ORACLE_URL: "https://gasprice.poa.network/" HOME_GAS_PRICE_SPEED_TYPE: "standard" HOME_GAS_PRICE_FALLBACK: 1000000000 # in wei HOME_GAS_PRICE_UPDATE_INTERVAL: 600000 +HOME_GAS_PRICE_FACTOR: 1 ## Foreign Gasprice FOREIGN_GAS_PRICE_ORACLE_URL: "https://gasprice.poa.network/" FOREIGN_GAS_PRICE_SPEED_TYPE: "standard" FOREIGN_GAS_PRICE_FALLBACK: 1000000000 # in wei FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000 +FOREIGN_GAS_PRICE_FACTOR: 1 ## UI UI_TITLE: "TokenBridge UI app - %c" @@ -45,7 +47,9 @@ UI_FOREIGN_GAS_PRICE_FALLBACK: 1000000000 MONITOR_PORT: 3003 MONITOR_HOME_DEPLOYMENT_BLOCK: 0 MONITOR_FOREIGN_DEPLOYMENT_BLOCK: 0 -MONITOR_GAS_LIMIT: 300000 -MONITOR_GAS_PRICE_FALLBACK: 21 +MONITOR_HOME_GAS_LIMIT: 300000 +MONITOR_FOREIGN_GAS_LIMIT: 300000 +MONITOR_HOME_GAS_PRICE_FALLBACK: 1000000000 +MONITOR_FOREIGN_GAS_PRICE_FALLBACK: 1000000000 MONITOR_LEFT_TX_THRESHOLD: 100 MONITOR_CRON_SCHEDULE: "* * * * *" diff --git a/deployment/group_vars/wetc.yml b/deployment/group_vars/wetc.yml index 9577442e..f24c5967 100644 --- a/deployment/group_vars/wetc.yml +++ b/deployment/group_vars/wetc.yml @@ -23,12 +23,14 @@ HOME_GAS_PRICE_ORACLE_URL: "https://gasprice-etc.poa.network/" HOME_GAS_PRICE_SPEED_TYPE: "standard" HOME_GAS_PRICE_FALLBACK: 15000000000 # in wei HOME_GAS_PRICE_UPDATE_INTERVAL: 600000 +HOME_GAS_PRICE_FACTOR: 1 ## Foreign Gasprice FOREIGN_GAS_PRICE_ORACLE_URL: "https://gasprice.poa.network/" FOREIGN_GAS_PRICE_SPEED_TYPE: "standard" FOREIGN_GAS_PRICE_FALLBACK: 10000000000 # in wei FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000 +FOREIGN_GAS_PRICE_FACTOR: 1 ## UI UI_TITLE: "TokenBridge UI app - %c" @@ -45,7 +47,9 @@ UI_FOREIGN_GAS_PRICE_FALLBACK: 10000000000 MONITOR_PORT: 3003 MONITOR_HOME_DEPLOYMENT_BLOCK: 7703292 MONITOR_FOREIGN_DEPLOYMENT_BLOCK: 7412459 -MONITOR_GAS_LIMIT: 300000 -MONITOR_GAS_PRICE_FALLBACK: 21 +MONITOR_HOME_GAS_LIMIT: 300000 +MONITOR_FOREIGN_GAS_LIMIT: 300000 +MONITOR_HOME_GAS_PRICE_FALLBACK: 15000000000 +MONITOR_FOREIGN_GAS_PRICE_FALLBACK: 10000000000 MONITOR_LEFT_TX_THRESHOLD: 100 MONITOR_CRON_SCHEDULE: "* * * * *" diff --git a/deployment/roles/monitor/templates/.env.j2 b/deployment/roles/monitor/templates/.env.j2 index 010c33e7..b6986660 100644 --- a/deployment/roles/monitor/templates/.env.j2 +++ b/deployment/roles/monitor/templates/.env.j2 @@ -4,9 +4,22 @@ HOME_BRIDGE_ADDRESS={{ HOME_BRIDGE_ADDRESS }} FOREIGN_BRIDGE_ADDRESS={{ FOREIGN_BRIDGE_ADDRESS }} HOME_DEPLOYMENT_BLOCK={{ MONITOR_HOME_DEPLOYMENT_BLOCK }} FOREIGN_DEPLOYMENT_BLOCK={{ MONITOR_FOREIGN_DEPLOYMENT_BLOCK }} -GAS_PRICE_SPEED_TYPE={{ HOME_GAS_PRICE_SPEED_TYPE }} -GAS_LIMIT={{ MONITOR_GAS_LIMIT }} -GAS_PRICE_FALLBACK={{ MONITOR_GAS_PRICE_FALLBACK }} +HOME_GAS_LIMIT={{ MONITOR_HOME_GAS_LIMIT }} +{% if HOME_GAS_PRICE_ORACLE_URL | default('') != '' %} +HOME_GAS_PRICE_ORACLE_URL={{ HOME_GAS_PRICE_ORACLE_URL }} +{% endif %} +{% if HOME_GAS_PRICE_SPEED_TYPE | default('') != '' %} +HOME_GAS_PRICE_SPEED_TYPE={{ HOME_GAS_PRICE_SPEED_TYPE }} +{% endif %} +HOME_GAS_PRICE_FALLBACK={{ MONITOR_HOME_GAS_PRICE_FALLBACK }} +{% if HOME_GAS_PRICE_FACTOR | default('') != '' %} +HOME_GAS_PRICE_FACTOR={{ HOME_GAS_PRICE_FACTOR }} +{% endif %} +FOREIGN_GAS_LIMIT={{ MONITOR_FOREIGN_GAS_LIMIT }} +FOREIGN_GAS_PRICE_ORACLE_URL={{ FOREIGN_GAS_PRICE_ORACLE_URL }} +FOREIGN_GAS_PRICE_SPEED_TYPE={{ FOREIGN_GAS_PRICE_SPEED_TYPE }} +FOREIGN_GAS_PRICE_FALLBACK={{ MONITOR_FOREIGN_GAS_PRICE_FALLBACK }} +FOREIGN_GAS_PRICE_FACTOR={{ FOREIGN_GAS_PRICE_FACTOR }} LEFT_TX_THRESHOLD={{ MONITOR_LEFT_TX_THRESHOLD }} PORT={{ MONITOR_PORT }} CRON_SCHEDULE={{ MONITOR_CRON_SCHEDULE }} diff --git a/deployment/roles/oracle/templates/.env.j2 b/deployment/roles/oracle/templates/.env.j2 index 25b1d05c..b0167927 100644 --- a/deployment/roles/oracle/templates/.env.j2 +++ b/deployment/roles/oracle/templates/.env.j2 @@ -23,6 +23,9 @@ HOME_GAS_PRICE_FALLBACK={{ HOME_GAS_PRICE_FALLBACK }} {% if HOME_GAS_PRICE_UPDATE_INTERVAL | default('') != '' %} HOME_GAS_PRICE_UPDATE_INTERVAL={{ HOME_GAS_PRICE_UPDATE_INTERVAL }} {% endif %} +{% if HOME_GAS_PRICE_FACTOR | default('') != '' %} +HOME_GAS_PRICE_FACTOR={{ HOME_GAS_PRICE_FACTOR }} +{% endif %} {% if FOREIGN_GAS_PRICE_ORACLE_URL | default('') != '' %} FOREIGN_GAS_PRICE_ORACLE_URL={{ FOREIGN_GAS_PRICE_ORACLE_URL }} @@ -34,6 +37,9 @@ FOREIGN_GAS_PRICE_FALLBACK={{ FOREIGN_GAS_PRICE_FALLBACK }} {% if FOREIGN_GAS_PRICE_UPDATE_INTERVAL | default('') != '' %} FOREIGN_GAS_PRICE_UPDATE_INTERVAL={{ FOREIGN_GAS_PRICE_UPDATE_INTERVAL }} {% endif %} +{% if FOREIGN_GAS_PRICE_FACTOR | default('') != '' %} +FOREIGN_GAS_PRICE_FACTOR={{ FOREIGN_GAS_PRICE_FACTOR }} +{% endif %} ## Transport configuration ALLOW_HTTP={{ "yes" if ALLOW_HTTP else "no" }} diff --git a/deployment/roles/ui/templates/.env.j2 b/deployment/roles/ui/templates/.env.j2 index 1b005841..eb263913 100644 --- a/deployment/roles/ui/templates/.env.j2 +++ b/deployment/roles/ui/templates/.env.j2 @@ -22,11 +22,15 @@ REACT_APP_HOME_GAS_PRICE_SPEED_TYPE={{ HOME_GAS_PRICE_SPEED_TYPE }} {% endif %} REACT_APP_HOME_GAS_PRICE_FALLBACK={{ UI_HOME_GAS_PRICE_FALLBACK }} REACT_APP_HOME_GAS_PRICE_UPDATE_INTERVAL={{ HOME_GAS_PRICE_UPDATE_INTERVAL }} +{% if HOME_GAS_PRICE_FACTOR | default('') != '' %} +REACT_APP_HOME_GAS_PRICE_FACTOR={{ HOME_GAS_PRICE_FACTOR }} +{% endif %} REACT_APP_FOREIGN_GAS_PRICE_ORACLE_URL={{ FOREIGN_GAS_PRICE_ORACLE_URL }} REACT_APP_FOREIGN_GAS_PRICE_SPEED_TYPE={{ FOREIGN_GAS_PRICE_SPEED_TYPE }} REACT_APP_FOREIGN_GAS_PRICE_FALLBACK={{ UI_FOREIGN_GAS_PRICE_FALLBACK }} REACT_APP_FOREIGN_GAS_PRICE_UPDATE_INTERVAL={{ FOREIGN_GAS_PRICE_UPDATE_INTERVAL }} +REACT_APP_FOREIGN_GAS_PRICE_FACTOR={{ FOREIGN_GAS_PRICE_FACTOR }} # Default REACT_APP_TITLE={{ UI_TITLE }} diff --git a/e2e-commons/docker-compose.yml b/e2e-commons/docker-compose.yml index 9ae356fb..06689717 100644 --- a/e2e-commons/docker-compose.yml +++ b/e2e-commons/docker-compose.yml @@ -37,10 +37,12 @@ services: - HOME_GAS_PRICE_SPEED_TYPE=standard - HOME_GAS_PRICE_FALLBACK=1 - HOME_GAS_PRICE_UPDATE_INTERVAL=600000 + - HOME_GAS_PRICE_FACTOR=1 - FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ - FOREIGN_GAS_PRICE_SPEED_TYPE=standard - FOREIGN_GAS_PRICE_FALLBACK=1 - FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000 + - FOREIGN_GAS_PRICE_FACTOR=0.1 - HOME_POLLING_INTERVAL=500 - FOREIGN_POLLING_INTERVAL=500 - ALLOW_HTTP=yes @@ -66,10 +68,12 @@ services: - HOME_GAS_PRICE_SPEED_TYPE=standard - HOME_GAS_PRICE_FALLBACK=1 - HOME_GAS_PRICE_UPDATE_INTERVAL=600000 + - HOME_GAS_PRICE_FACTOR=1 - FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ - FOREIGN_GAS_PRICE_SPEED_TYPE=standard - FOREIGN_GAS_PRICE_FALLBACK=1 - FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000 + - FOREIGN_GAS_PRICE_FACTOR=0.1 - HOME_POLLING_INTERVAL=500 - FOREIGN_POLLING_INTERVAL=500 - ALLOW_HTTP=yes @@ -95,10 +99,12 @@ services: - HOME_GAS_PRICE_SPEED_TYPE=standard - HOME_GAS_PRICE_FALLBACK=1 - HOME_GAS_PRICE_UPDATE_INTERVAL=600000 + - HOME_GAS_PRICE_FACTOR=1 - FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ - FOREIGN_GAS_PRICE_SPEED_TYPE=standard - FOREIGN_GAS_PRICE_FALLBACK=1 - FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000 + - FOREIGN_GAS_PRICE_FACTOR=0.1 - HOME_POLLING_INTERVAL=500 - FOREIGN_POLLING_INTERVAL=500 - ALLOW_HTTP=yes @@ -123,10 +129,12 @@ services: - REACT_APP_HOME_GAS_PRICE_SPEED_TYPE=standard - REACT_APP_HOME_GAS_PRICE_FALLBACK=5000000000 - REACT_APP_HOME_GAS_PRICE_UPDATE_INTERVAL=15000 + - REACT_APP_HOME_GAS_PRICE_FACTOR=1 - REACT_APP_FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ - REACT_APP_FOREIGN_GAS_PRICE_SPEED_TYPE=standard - REACT_APP_FOREIGN_GAS_PRICE_FALLBACK=5000000000 - REACT_APP_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=15000 + - REACT_APP_FOREIGN_GAS_PRICE_FACTOR=1 - PORT=3000 command: "true" ui-erc20: @@ -149,10 +157,12 @@ services: - REACT_APP_HOME_GAS_PRICE_SPEED_TYPE=standard - REACT_APP_HOME_GAS_PRICE_FALLBACK=5000000000 - REACT_APP_HOME_GAS_PRICE_UPDATE_INTERVAL=15000 + - REACT_APP_HOME_GAS_PRICE_FACTOR=1 - REACT_APP_FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ - REACT_APP_FOREIGN_GAS_PRICE_SPEED_TYPE=standard - REACT_APP_FOREIGN_GAS_PRICE_FALLBACK=5000000000 - REACT_APP_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=15000 + - REACT_APP_FOREIGN_GAS_PRICE_FACTOR=1 - PORT=3000 command: "true" ui-erc20-native: @@ -175,10 +185,12 @@ services: - REACT_APP_HOME_GAS_PRICE_SPEED_TYPE=standard - REACT_APP_HOME_GAS_PRICE_FALLBACK=5000000000 - REACT_APP_HOME_GAS_PRICE_UPDATE_INTERVAL=15000 + - REACT_APP_HOME_GAS_PRICE_FACTOR=1 - REACT_APP_FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ - REACT_APP_FOREIGN_GAS_PRICE_SPEED_TYPE=standard - REACT_APP_FOREIGN_GAS_PRICE_FALLBACK=5000000000 - REACT_APP_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=15000 + - REACT_APP_FOREIGN_GAS_PRICE_FACTOR=1 - PORT=3000 command: "true" monitor: @@ -192,9 +204,16 @@ services: - FOREIGN_BRIDGE_ADDRESS=0x2B6871b9B02F73fa24F4864322CdC78604207769 - HOME_DEPLOYMENT_BLOCK=0 - FOREIGN_DEPLOYMENT_BLOCK=0 - - GAS_PRICE_SPEED_TYPE=standard - - GAS_LIMIT=300000 - - GAS_PRICE_FALLBACK=21 + - HOME_GAS_LIMIT=300000 + - HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ + - HOME_GAS_PRICE_SPEED_TYPE=standard + - HOME_GAS_PRICE_FALLBACK=1000000000 + - HOME_GAS_PRICE_FACTOR=1 + - FOREIGN_GAS_LIMIT=300000 + - FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ + - FOREIGN_GAS_PRICE_SPEED_TYPE=standard + - FOREIGN_GAS_PRICE_FALLBACK=1000000000 + - FOREIGN_GAS_PRICE_FACTOR=1 - LEFT_TX_THRESHOLD=100 - PORT=3003 entrypoint: yarn start diff --git a/monitor/.env.example b/monitor/.env.example index 1af8bbfd..feb7c3af 100644 --- a/monitor/.env.example +++ b/monitor/.env.example @@ -4,8 +4,18 @@ HOME_BRIDGE_ADDRESS=0xABb4C1399DcC28FBa3Beb76CAE2b50Be3e087353 FOREIGN_BRIDGE_ADDRESS=0xE405F6872cE38a7a4Ff63DcF946236D458c2ca3a HOME_DEPLOYMENT_BLOCK=0 FOREIGN_DEPLOYMENT_BLOCK=0 -GAS_PRICE_SPEED_TYPE=standard -GAS_LIMIT=300000 -GAS_PRICE_FALLBACK=21 + +HOME_GAS_LIMIT=300000 +HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ +HOME_GAS_PRICE_SPEED_TYPE=standard +HOME_GAS_PRICE_FALLBACK=1000000000 +HOME_GAS_PRICE_FACTOR=1 + +FOREIGN_GAS_LIMIT=300000 +FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ +FOREIGN_GAS_PRICE_SPEED_TYPE=standard +FOREIGN_GAS_PRICE_FALLBACK=1000000000 +FOREIGN_GAS_PRICE_FACTOR=1 + LEFT_TX_THRESHOLD=100 PORT=3003 diff --git a/monitor/validators.js b/monitor/validators.js index 1ea16051..d686e8ae 100644 --- a/monitor/validators.js +++ b/monitor/validators.js @@ -11,9 +11,16 @@ const { FOREIGN_RPC_URL, HOME_BRIDGE_ADDRESS, FOREIGN_BRIDGE_ADDRESS, - GAS_PRICE_SPEED_TYPE, - GAS_LIMIT, - GAS_PRICE_FALLBACK + HOME_GAS_LIMIT, + HOME_GAS_PRICE_ORACLE_URL, + HOME_GAS_PRICE_SPEED_TYPE, + HOME_GAS_PRICE_FALLBACK, + HOME_GAS_PRICE_FACTOR, + FOREIGN_GAS_LIMIT, + FOREIGN_GAS_PRICE_ORACLE_URL, + FOREIGN_GAS_PRICE_SPEED_TYPE, + FOREIGN_GAS_PRICE_FALLBACK, + FOREIGN_GAS_PRICE_FACTOR } = process.env const HOME_DEPLOYMENT_BLOCK = Number(process.env.HOME_DEPLOYMENT_BLOCK) || 0 const FOREIGN_DEPLOYMENT_BLOCK = Number(process.env.FOREIGN_DEPLOYMENT_BLOCK) || 0 @@ -32,18 +39,34 @@ const asyncForEach = async (array, callback) => { } } -async function getGasPrices(type) { +function getGasPrices(url, type, factor, fallback) { + if (!url) { + return Web3Utils.toBN(fallback) + } + return fetchGasPrices(url, type, factor, fallback) +} + +async function fetchGasPrices(url, type, factor, fallback) { try { - const response = await fetch('https://gasprice.poa.network/') + const response = await fetch(url) const json = await response.json() logger.log('Fetched gasprice: ' + json[type]) - return json[type] + const gasPrice = json[type] + if (!gasPrice) { + throw new Error(`Response from Oracle didn't include gas price for ${type} type.`) + } + return normalizeGasPrice(gasPrice, factor) } catch (e) { logger.error('Gas Price API is not available', e) - return GAS_PRICE_FALLBACK + return Web3Utils.toBN(fallback) } } +function normalizeGasPrice(oracleGasPrice, factor) { + const gasPrice = oracleGasPrice * factor + return Web3Utils.toBN(Web3Utils.toWei(gasPrice.toFixed(2).toString(), 'gwei')) +} + async function main(bridgeMode) { const { HOME_ABI, FOREIGN_ABI } = getBridgeABIs(bridgeMode) const homeBridge = new web3Home.eth.Contract(HOME_ABI, HOME_BRIDGE_ADDRESS) @@ -87,19 +110,38 @@ async function main(bridgeMode) { }) const foreignVBalances = {} const homeVBalances = {} - logger.debug('calling getGasPrices') - const gasPriceInGwei = await getGasPrices(GAS_PRICE_SPEED_TYPE) - const gasPrice = new Web3Utils.BN(Web3Utils.toWei(gasPriceInGwei.toString(10), 'gwei')) - const txCost = gasPrice.mul(new Web3Utils.BN(GAS_LIMIT)) + + logger.debug('calling home getGasPrices') + const homeGasPrice = await getGasPrices( + HOME_GAS_PRICE_ORACLE_URL, + HOME_GAS_PRICE_SPEED_TYPE, + HOME_GAS_PRICE_FACTOR, + HOME_GAS_PRICE_FALLBACK + ) + const homeGasPriceGwei = Web3Utils.fromWei(homeGasPrice.toString(), 'gwei') + const homeTxCost = homeGasPrice.mul(Web3Utils.toBN(HOME_GAS_LIMIT)) + + logger.debug('calling foreign getGasPrices') + const foreignGasPrice = await getGasPrices( + FOREIGN_GAS_PRICE_ORACLE_URL, + FOREIGN_GAS_PRICE_SPEED_TYPE, + FOREIGN_GAS_PRICE_FACTOR, + FOREIGN_GAS_PRICE_FALLBACK + ) + const foreignGasPriceGwei = Web3Utils.fromWei(foreignGasPrice.toString(), 'gwei') + const foreignTxCost = foreignGasPrice.mul(Web3Utils.toBN(FOREIGN_GAS_LIMIT)) + let validatorsMatch = true logger.debug('calling asyncForEach foreignValidators foreignVBalances') await asyncForEach(foreignValidators, async v => { const balance = await web3Foreign.eth.getBalance(v) - const leftTx = new Web3Utils.BN(balance).div(txCost).toString(10) + const leftTx = Web3Utils.toBN(balance) + .div(foreignTxCost) + .toString(10) foreignVBalances[v] = { balance: Web3Utils.fromWei(balance), leftTx: Number(leftTx), - gasPrice: gasPriceInGwei + gasPrice: Number(foreignGasPriceGwei) } if (!homeValidators.includes(v)) { validatorsMatch = false @@ -108,14 +150,16 @@ async function main(bridgeMode) { }) logger.debug('calling asyncForEach homeValidators homeVBalances') await asyncForEach(homeValidators, async v => { - const gasPrice = new Web3Utils.BN(1) - const txCost = gasPrice.mul(new Web3Utils.BN(GAS_LIMIT)) const balance = await web3Home.eth.getBalance(v) - const leftTx = new Web3Utils.BN(balance).div(txCost).toString(10) + const leftTx = homeTxCost.isZero() + ? 999999 + : Web3Utils.toBN(balance) + .div(homeTxCost) + .toString(10) homeVBalances[v] = { balance: Web3Utils.fromWei(balance), leftTx: Number(leftTx), - gasPrice: Number(gasPrice.toString(10)) + gasPrice: Number(homeGasPriceGwei) } if (!foreignValidators.includes(v)) { validatorsMatch = false diff --git a/oracle/.env.example b/oracle/.env.example index f6d7c482..6f89a1bb 100644 --- a/oracle/.env.example +++ b/oracle/.env.example @@ -14,11 +14,13 @@ HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ HOME_GAS_PRICE_SPEED_TYPE=standard HOME_GAS_PRICE_FALLBACK=1000000000 HOME_GAS_PRICE_UPDATE_INTERVAL=600000 +HOME_GAS_PRICE_FACTOR=1 FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ FOREIGN_GAS_PRICE_SPEED_TYPE=standard FOREIGN_GAS_PRICE_FALLBACK=1000000000 FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000 +FOREIGN_GAS_PRICE_FACTOR=1 QUEUE_URL=amqp://rabbit REDIS_URL=redis://redis diff --git a/oracle/README.md b/oracle/README.md index c3d98744..53d9d6e6 100644 --- a/oracle/README.md +++ b/oracle/README.md @@ -180,10 +180,12 @@ where the _watcher_ could be one of: | `HOME_GAS_PRICE_SPEED_TYPE` | Assuming the gas price oracle responds with the following JSON structure: `{"fast": 20.0, "block_time": 12.834, "health": true, "standard": 6.0, "block_number": 6470469, "instant": 71.0, "slow": 1.889}`, this parameter specifies the desirable transaction speed. The speed type can be omitted when `HOME_GAS_PRICE_ORACLE_URL` is not used. | `instant` / `fast` / `standard` / `slow` | | `HOME_GAS_PRICE_FALLBACK` | The gas price (in Wei) that is used if both the oracle and the fall back gas price specified in the Home Bridge contract are not available. | integer | | `HOME_GAS_PRICE_UPDATE_INTERVAL` | An interval in milliseconds used to get the updated gas price value either from the oracle or from the Home Bridge contract. | integer | +| `HOME_GAS_PRICE_FACTOR` | A value that will multiply the gas price of the oracle to convert it to gwei. If the oracle API returns gas prices in gwei then this can be set to `1`. Also, it could be used to intentionally pay more gas than suggested by the oracle to guarantee the transaction verification. E.g. `1.25` or `1.5`. | integer | | `FOREIGN_GAS_PRICE_ORACLE_URL` | The URL used to get a JSON response from the gas price prediction oracle for the Foreign network. The provided gas price is used to send the validator's transactions to the RPC node. If the Foreign network is Ethereum Foundation mainnet, the oracle URL can be: https://gasprice.poa.network. Otherwise this parameter can be omitted. | URL | | `FOREIGN_GAS_PRICE_SPEED_TYPE` | Assuming the gas price oracle responds with the following JSON structure: `{"fast": 20.0, "block_time": 12.834, "health": true, "standard": 6.0, "block_number": 6470469, "instant": 71.0, "slow": 1.889}`, this parameter specifies the desirable transaction speed. The speed type can be omitted when `FOREIGN_GAS_PRICE_ORACLE_URL`is not used. | `instant` / `fast` / `standard` / `slow` | | `FOREIGN_GAS_PRICE_FALLBACK` | The gas price (in Wei) used if both the oracle and fall back gas price specified in the Foreign Bridge contract are not available. | integer | | `FOREIGN_GAS_PRICE_UPDATE_INTERVAL` | The interval in milliseconds used to get the updated gas price value either from the oracle or from the Foreign Bridge contract. | integer | +| `FOREIGN_GAS_PRICE_FACTOR` | A value that will multiply the gas price of the oracle to convert it to gwei. If the oracle API returns gas prices in gwei then this can be set to `1`. Also, it could be used to intentionally pay more gas than suggested by the oracle to guarantee the transaction verification. E.g. `1.25` or `1.5`. | integer | | `VALIDATOR_ADDRESS_PRIVATE_KEY` | The private key of the bridge validator used to sign confirmations before sending transactions to the bridge contracts. The validator account is calculated automatically from the private key. Every bridge instance (set of watchers and senders) must have its own unique private key. The specified private key is used to sign transactions on both sides of the bridge. | hexidecimal without "0x" | | `HOME_START_BLOCK` | The block number in the Home network used to start watching for events when the bridge instance is run for the first time. Usually this is the same block where the Home Bridge contract is deployed. If a new validator instance is being deployed for an existing set of validators, the block number could be the latest block in the chain. | integer | | `FOREIGN_START_BLOCK` | The block number in the Foreign network used to start watching for events when the bridge instance runs for the first time. Usually this is the same block where the Foreign Bridge contract was deployed to. If a new validator instance is being deployed for an existing set of validators, the block number could be the latest block in the chain. | integer | diff --git a/oracle/src/services/gasPrice.js b/oracle/src/services/gasPrice.js index bd25716d..ad8f1d19 100644 --- a/oracle/src/services/gasPrice.js +++ b/oracle/src/services/gasPrice.js @@ -7,7 +7,11 @@ const logger = require('../services/logger').child({ module: 'gasPrice' }) const { setIntervalAndRun } = require('../utils/utils') -const { DEFAULT_UPDATE_INTERVAL, GAS_PRICE_BOUNDARIES } = require('../utils/constants') +const { + DEFAULT_UPDATE_INTERVAL, + GAS_PRICE_BOUNDARIES, + DEFAULT_GAS_PRICE_FACTOR +} = require('../utils/constants') const HomeABI = bridgeConfig.homeBridgeAbi const ForeignABI = bridgeConfig.foreignBridgeAbi @@ -18,11 +22,13 @@ const { FOREIGN_GAS_PRICE_ORACLE_URL, FOREIGN_GAS_PRICE_SPEED_TYPE, FOREIGN_GAS_PRICE_UPDATE_INTERVAL, + FOREIGN_GAS_PRICE_FACTOR, HOME_BRIDGE_ADDRESS, HOME_GAS_PRICE_FALLBACK, HOME_GAS_PRICE_ORACLE_URL, HOME_GAS_PRICE_SPEED_TYPE, - HOME_GAS_PRICE_UPDATE_INTERVAL + HOME_GAS_PRICE_UPDATE_INTERVAL, + HOME_GAS_PRICE_FACTOR } = process.env const homeBridge = new web3Home.eth.Contract(HomeABI, HOME_BRIDGE_ADDRESS) @@ -41,15 +47,21 @@ function gasPriceWithinLimits(gasPrice) { } } -async function fetchGasPriceFromOracle(oracleUrl, speedType) { +function normalizeGasPrice(oracleGasPrice, factor) { + const gasPriceGwei = oracleGasPrice * factor + const gasPrice = gasPriceWithinLimits(gasPriceGwei) + return Web3Utils.toWei(gasPrice.toFixed(2).toString(), 'gwei') +} + +async function fetchGasPriceFromOracle(oracleUrl, speedType, factor) { const response = await fetch(oracleUrl) const json = await response.json() const oracleGasPrice = json[speedType] if (!oracleGasPrice) { throw new Error(`Response from Oracle didn't include gas price for ${speedType} type.`) } - const gasPrice = gasPriceWithinLimits(oracleGasPrice) - return Web3Utils.toWei(gasPrice.toString(), 'gwei') + + return normalizeGasPrice(oracleGasPrice, factor) } async function fetchGasPrice({ bridgeContract, oracleFn }) { @@ -79,11 +91,13 @@ async function start(chainId) { let oracleUrl = null let speedType = null let updateInterval = null + let factor = null if (chainId === 'home') { bridgeContract = homeBridge oracleUrl = HOME_GAS_PRICE_ORACLE_URL speedType = HOME_GAS_PRICE_SPEED_TYPE updateInterval = HOME_GAS_PRICE_UPDATE_INTERVAL || DEFAULT_UPDATE_INTERVAL + factor = Number(HOME_GAS_PRICE_FACTOR) || DEFAULT_GAS_PRICE_FACTOR cachedGasPrice = HOME_GAS_PRICE_FALLBACK } else if (chainId === 'foreign') { @@ -91,6 +105,7 @@ async function start(chainId) { oracleUrl = FOREIGN_GAS_PRICE_ORACLE_URL speedType = FOREIGN_GAS_PRICE_SPEED_TYPE updateInterval = FOREIGN_GAS_PRICE_UPDATE_INTERVAL || DEFAULT_UPDATE_INTERVAL + factor = Number(FOREIGN_GAS_PRICE_FACTOR) || DEFAULT_GAS_PRICE_FACTOR cachedGasPrice = FOREIGN_GAS_PRICE_FALLBACK } else { @@ -100,7 +115,7 @@ async function start(chainId) { fetchGasPriceInterval = setIntervalAndRun(async () => { const gasPrice = await fetchGasPrice({ bridgeContract, - oracleFn: () => fetchGasPriceFromOracle(oracleUrl, speedType) + oracleFn: () => fetchGasPriceFromOracle(oracleUrl, speedType, factor) }) cachedGasPrice = gasPrice || cachedGasPrice }, updateInterval) @@ -114,5 +129,6 @@ module.exports = { start, fetchGasPrice, getPrice, - gasPriceWithinLimits + gasPriceWithinLimits, + normalizeGasPrice } diff --git a/oracle/src/utils/constants.js b/oracle/src/utils/constants.js index 28f5d8dd..162a8346 100644 --- a/oracle/src/utils/constants.js +++ b/oracle/src/utils/constants.js @@ -8,6 +8,7 @@ module.exports = { randomize: true }, DEFAULT_UPDATE_INTERVAL: 600000, + DEFAULT_GAS_PRICE_FACTOR: 1, EXIT_CODES: { GENERAL_ERROR: 1, INCOMPATIBILITY: 10, diff --git a/oracle/test/gasPrice.test.js b/oracle/test/gasPrice.test.js index 6707de92..aa4eba0c 100644 --- a/oracle/test/gasPrice.test.js +++ b/oracle/test/gasPrice.test.js @@ -1,7 +1,12 @@ const sinon = require('sinon') const { expect } = require('chai') const proxyquire = require('proxyquire').noPreserveCache() -const { fetchGasPrice, gasPriceWithinLimits } = require('../src/services/gasPrice') +const Web3Utils = require('web3-utils') +const { + fetchGasPrice, + gasPriceWithinLimits, + normalizeGasPrice +} = require('../src/services/gasPrice') const { DEFAULT_UPDATE_INTERVAL, GAS_PRICE_BOUNDARIES } = require('../src/utils/constants') describe('gasPrice', () => { @@ -176,4 +181,63 @@ describe('gasPrice', () => { expect(gasPrice).to.equal(GAS_PRICE_BOUNDARIES.MAX) }) }) + describe('normalizeGasPrice', () => { + it('should work with oracle gas price in gwei', () => { + // Given + const oracleGasPrice = 20 + const factor = 1 + + // When + const result = normalizeGasPrice(oracleGasPrice, factor) + + // Then + expect(result).to.equal('20000000000') + }) + it('should work with oracle gas price not in gwei', () => { + // Given + const oracleGasPrice = 200 + const factor = 0.1 + + // When + const result = normalizeGasPrice(oracleGasPrice, factor) + + // Then + expect(result).to.equal('20000000000') + }) + it('should increase gas price value from oracle', () => { + // Given + const oracleGasPrice = 20 + const factor = 1.5 + + // When + const result = normalizeGasPrice(oracleGasPrice, factor) + + // Then + expect(result).to.equal('30000000000') + }) + it('should respect gas price max limit', () => { + // Given + const oracleGasPrice = 200 + const factor = 4 + const maxInWei = Web3Utils.toWei(GAS_PRICE_BOUNDARIES.MAX.toString(), 'gwei') + + // When + const result = normalizeGasPrice(oracleGasPrice, factor) + + // Then + expect(result).to.equal(maxInWei) + }) + it('should respect gas price min limit', () => { + // Given + const oracleGasPrice = 1 + const factor = 0.01 + const minInWei = Web3Utils.toWei(GAS_PRICE_BOUNDARIES.MIN.toString(), 'gwei') + + // When + const result = normalizeGasPrice(oracleGasPrice, factor) + + // Then + expect(result).to.equal(minInWei) + }) + }) }) diff --git a/ui/.env.example b/ui/.env.example index fe9f865c..6e8aa232 100644 --- a/ui/.env.example +++ b/ui/.env.example @@ -22,11 +22,13 @@ REACT_APP_HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ REACT_APP_HOME_GAS_PRICE_SPEED_TYPE=standard REACT_APP_HOME_GAS_PRICE_FALLBACK=5000000000 REACT_APP_HOME_GAS_PRICE_UPDATE_INTERVAL=15000 +REACT_APP_HOME_GAS_PRICE_FACTOR=1 REACT_APP_FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/ REACT_APP_FOREIGN_GAS_PRICE_SPEED_TYPE=standard REACT_APP_FOREIGN_GAS_PRICE_FALLBACK=5000000000 REACT_APP_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=15000 +REACT_APP_FOREIGN_GAS_PRICE_FACTOR=1 # Default REACT_APP_TITLE=TokenBridge UI app - %c diff --git a/ui/README.md b/ui/README.md index 255d371b..77d3c4c0 100644 --- a/ui/README.md +++ b/ui/README.md @@ -177,10 +177,12 @@ REACT_APP_HOME_GAS_PRICE_ORACLE_URL | The URL used to get a JSON response from t REACT_APP_HOME_GAS_PRICE_SPEED_TYPE | Gas Price speed (slow, standard, fast, instant) REACT_APP_HOME_GAS_PRICE_FALLBACK | The gas price (in Wei) that is used if both the oracle and the fall back gas price specified in the Home Bridge contract are not available. REACT_APP_HOME_GAS_PRICE_UPDATE_INTERVAL | An interval in milliseconds used to get the updated gas price value either from the oracle or from the Home Bridge contract. +REACT_APP_HOME_GAS_PRICE_FACTOR | A value that will multiply the gas price of the oracle to convert it to gwei. If the oracle API returns gas prices in gwei then this can be set to `1`. Also, it could be used to intentionally pay more gas than suggested by the oracle to guarantee the transaction verification. E.g. `1.25` or `1.5`. REACT_APP_FOREIGN_GAS_PRICE_ORACLE_URL | The URL used to get a JSON response from the gas price prediction oracle for Foreign network. REACT_APP_FOREIGN_GAS_PRICE_SPEED_TYPE | Gas Price speed (slow, standard, fast, instant) REACT_APP_FOREIGN_GAS_PRICE_FALLBACK | The gas price (in Wei) that is used if both the oracle and the fall back gas price specified in the Foreign Bridge contract are not available. REACT_APP_FOREIGN_GAS_PRICE_UPDATE_INTERVAL | An interval in milliseconds used to get the updated gas price value either from the oracle or from the Foreign Bridge contract. +REACT_APP_FOREIGN_GAS_PRICE_FACTOR | A value that will multiply the gas price of the oracle to convert it to gwei. If the oracle API returns gas prices in gwei then this can be set to `1`. Also, it could be used to intentionally pay more gas than suggested by the oracle to guarantee the transaction verification. E.g. `1.25` or `1.5`. REACT_APP_TITLE | The title for the bridge UI page. `%c` will be replaced by the name of the network. REACT_APP_DESCRIPTION | The meta description for the deployed bridge page. APP_STYLES | The set of styles to render the bridge UI page. Currently only `classic` is implemented diff --git a/ui/src/stores/GasPriceStore.js b/ui/src/stores/GasPriceStore.js index 7bcd9435..1a42a989 100644 --- a/ui/src/stores/GasPriceStore.js +++ b/ui/src/stores/GasPriceStore.js @@ -6,19 +6,23 @@ const HOME_GAS_PRICE_FALLBACK = process.env.REACT_APP_HOME_GAS_PRICE_FALLBACK const HOME_GAS_PRICE_ORACLE_URL = process.env.REACT_APP_HOME_GAS_PRICE_ORACLE_URL const HOME_GAS_PRICE_SPEED_TYPE = process.env.REACT_APP_HOME_GAS_PRICE_SPEED_TYPE const HOME_GAS_PRICE_UPDATE_INTERVAL = process.env.REACT_APP_HOME_GAS_PRICE_UPDATE_INTERVAL +const HOME_GAS_PRICE_FACTOR = process.env.REACT_APP_HOME_GAS_PRICE_FACTOR const FOREIGN_GAS_PRICE_FALLBACK = process.env.REACT_APP_FOREIGN_GAS_PRICE_FALLBACK const FOREIGN_GAS_PRICE_ORACLE_URL = process.env.REACT_APP_FOREIGN_GAS_PRICE_ORACLE_URL const FOREIGN_GAS_PRICE_SPEED_TYPE = process.env.REACT_APP_FOREIGN_GAS_PRICE_SPEED_TYPE const FOREIGN_GAS_PRICE_UPDATE_INTERVAL = process.env.REACT_APP_FOREIGN_GAS_PRICE_UPDATE_INTERVAL +const FOREIGN_GAS_PRICE_FACTOR = process.env.REACT_APP_FOREIGN_GAS_PRICE_FACTOR + +const DEFAULT_GAS_PRICE_FACTOR = 1 +const DEFAULT_GAS_PRICE_UPDATE_INTERVAL = 900000 class GasPriceStore { @observable gasPrice = null - oracleUrl = null speedType = null updateInterval = null - bridgeContract = null + factor = null constructor(rootStore) { this.alertStore = rootStore.alertStore @@ -36,19 +40,18 @@ class GasPriceStore { this.gasPrice = HOME_GAS_PRICE_FALLBACK this.oracleUrl = HOME_GAS_PRICE_ORACLE_URL this.speedType = HOME_GAS_PRICE_SPEED_TYPE - this.updateInterval = HOME_GAS_PRICE_UPDATE_INTERVAL || 900000 - this.bridgeContract = this.homeStore.homeBridge + this.updateInterval = HOME_GAS_PRICE_UPDATE_INTERVAL || DEFAULT_GAS_PRICE_UPDATE_INTERVAL + this.factor = Number(HOME_GAS_PRICE_FACTOR) || DEFAULT_GAS_PRICE_FACTOR } else { this.gasPrice = FOREIGN_GAS_PRICE_FALLBACK this.oracleUrl = FOREIGN_GAS_PRICE_ORACLE_URL this.speedType = FOREIGN_GAS_PRICE_SPEED_TYPE - this.updateInterval = FOREIGN_GAS_PRICE_UPDATE_INTERVAL || 900000 - this.bridgeContract = this.foreignStore.foreignBridge + this.updateInterval = FOREIGN_GAS_PRICE_UPDATE_INTERVAL || DEFAULT_GAS_PRICE_UPDATE_INTERVAL + this.factor = Number(FOREIGN_GAS_PRICE_FACTOR) || DEFAULT_GAS_PRICE_FACTOR } const newGasPrice = await fetchGasPrice({ - bridgeContract: this.bridgeContract, - oracleFn: () => fetchGasPriceFromOracle(this.oracleUrl, this.speedType) + oracleFn: () => fetchGasPriceFromOracle(this.oracleUrl, this.speedType, this.factor) }) this.gasPrice = newGasPrice || this.gasPrice diff --git a/ui/src/stores/utils/__tests__/gas.test.js b/ui/src/stores/utils/__tests__/gas.test.js new file mode 100644 index 00000000..13f6574b --- /dev/null +++ b/ui/src/stores/utils/__tests__/gas.test.js @@ -0,0 +1,37 @@ +import { normalizeGasPrice } from '../gas' + +describe('normalizeGasPrice', () => { + it('should work with oracle gas price in gwei', () => { + // Given + const oracleGasPrice = 30 + const factor = 1 + + // When + const result = normalizeGasPrice(oracleGasPrice, factor) + + // Then + expect(result).toEqual('30000000000') + }) + it('should work with oracle gas price not in gwei', () => { + // Given + const oracleGasPrice = 300 + const factor = 0.1 + + // When + const result = normalizeGasPrice(oracleGasPrice, factor) + + // Then + expect(result).toEqual('30000000000') + }) + it('should increase gas price value from oracle', () => { + // Given + const oracleGasPrice = 20 + const factor = 1.5 + + // When + const result = normalizeGasPrice(oracleGasPrice, factor) + + // Then + expect(result).toEqual('30000000000') + }) +}) diff --git a/ui/src/stores/utils/gas.js b/ui/src/stores/utils/gas.js index 6d92c456..3eb30730 100644 --- a/ui/src/stores/utils/gas.js +++ b/ui/src/stores/utils/gas.js @@ -12,7 +12,7 @@ export async function fetchGasPrice({ oracleFn }) { return gasPrice } -export async function fetchGasPriceFromOracle(oracleUrl, speedType) { +export async function fetchGasPriceFromOracle(oracleUrl, speedType, factor) { if (!oracleUrl) { throw new Error(`Gas Price Oracle url not defined`) } @@ -22,5 +22,10 @@ export async function fetchGasPriceFromOracle(oracleUrl, speedType) { if (!gasPrice) { throw new Error(`Response from Oracle didn't include gas price for ${speedType} type.`) } - return toWei(gasPrice.toString(), 'gwei') + return normalizeGasPrice(gasPrice, factor) +} + +export function normalizeGasPrice(oracleGasPrice, factor) { + const gasPrice = oracleGasPrice * factor + return toWei(gasPrice.toFixed(2).toString(), 'gwei') }