Add support for oracle gas price values not expressed in gwei (#142)

* Support other oracle's gas price values in Oracle
* Add default gas price factor in Oracle
* Support other oracle's gas price values in UI
* Support other oracle's gas price values in Monitor
This commit is contained in:
Gerardo Nardelli 2019-07-12 13:10:17 -03:00 committed by Alexander Kolotov
parent 54f6fb5835
commit 811e8da6b5
19 changed files with 291 additions and 50 deletions

@ -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: "* * * * *"

@ -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: "* * * * *"

@ -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: "* * * * *"

@ -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 }}

@ -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" }}

@ -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 }}

@ -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

@ -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

@ -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

@ -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

@ -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 |

@ -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
}

@ -8,6 +8,7 @@ module.exports = {
randomize: true
},
DEFAULT_UPDATE_INTERVAL: 600000,
DEFAULT_GAS_PRICE_FACTOR: 1,
EXIT_CODES: {
GENERAL_ERROR: 1,
INCOMPATIBILITY: 10,

@ -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)
})
})
})

@ -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

@ -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

@ -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

@ -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')
})
})

@ -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')
}