fix: calculate optimism l1 fee

This commit is contained in:
Danil Kovtonyuk 2022-05-27 00:04:27 +10:00
parent fa3d089e44
commit dc5a72b85a
6 changed files with 235 additions and 10 deletions

@ -0,0 +1,151 @@
[
{
"inputs": [{ "internalType": "address", "name": "_owner", "type": "address" }],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "DecimalsUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "GasPriceUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "L1BaseFeeUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "OverheadUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" },
{ "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" }
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "ScalarUpdated",
"type": "event"
},
{
"inputs": [],
"name": "decimals",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "gasPrice",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "bytes", "name": "_data", "type": "bytes" }],
"name": "getL1Fee",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "bytes", "name": "_data", "type": "bytes" }],
"name": "getL1GasUsed",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l1BaseFee",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "overhead",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "scalar",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_decimals", "type": "uint256" }],
"name": "setDecimals",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_gasPrice", "type": "uint256" }],
"name": "setGasPrice",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_baseFee", "type": "uint256" }],
"name": "setL1BaseFee",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_overhead", "type": "uint256" }],
"name": "setOverhead",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_scalar", "type": "uint256" }],
"name": "setScalar",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]

@ -17,7 +17,7 @@
</div> </div>
<div v-if="withdrawType === 'relayer'" class="withdraw-data-item"> <div v-if="withdrawType === 'relayer'" class="withdraw-data-item">
{{ $t('networkFee') }} {{ $t('networkFee') }}
<span>{{ networkFeeInEth }} {{ networkCurrency }}</span> <span>{{ toDecimals(networkFee, null, 6) }} {{ networkCurrency }}</span>
</div> </div>
<div v-if="withdrawType === 'relayer'" class="withdraw-data-item"> <div v-if="withdrawType === 'relayer'" class="withdraw-data-item">
{{ $t('relayerFee') }} {{ $t('relayerFee') }}
@ -76,9 +76,6 @@ export default {
...mapGetters('token', ['toDecimals', 'fromDecimals']), ...mapGetters('token', ['toDecimals', 'fromDecimals']),
...mapGetters('application', ['networkFee']), ...mapGetters('application', ['networkFee']),
...mapGetters('price', ['tokenRate']), ...mapGetters('price', ['tokenRate']),
networkFeeInEth() {
return fromWei(this.networkFee)
},
relayerFee() { relayerFee() {
const { amount } = this.selectedStatistic const { amount } = this.selectedStatistic
const total = toBN(this.fromDecimals(amount.toString())) const total = toBN(this.fromDecimals(amount.toString()))

@ -87,3 +87,8 @@ export const trees = {
PARTS_COUNT: 4, PARTS_COUNT: 4,
LEVELS: 20 // const from contract LEVELS: 20 // const from contract
} }
export const DUMMY_NONCE = '0x1111111111111111111111111111111111111111111111111111111111111111'
export const DUMMY_WITHDRAW_DATA =
'0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111'

@ -249,6 +249,7 @@ export default {
deployedBlock: 2243689, deployedBlock: 2243689,
multicall: '0x35A6Cdb2C9AD4a45112df4a04147EB07dFA01aB7', multicall: '0x35A6Cdb2C9AD4a45112df4a04147EB07dFA01aB7',
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4', echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
ovmGasPriceOracleContract: '0x420000000000000000000000000000000000000F',
rpcUrls: { rpcUrls: {
Alchemy: { Alchemy: {
name: 'Alchemy', name: 'Alchemy',

@ -148,19 +148,18 @@ const getters = {
currentContract: (state, getters) => (params) => { currentContract: (state, getters) => (params) => {
return getters.tornadoProxyContract(params) return getters.tornadoProxyContract(params)
}, },
withdrawGas: (state, getters, rootState, rootGetters) => { withdrawGas: (state, getters) => {
const netId = rootGetters['metamask/netId']
let action = ACTION.WITHDRAW_WITH_EXTRA let action = ACTION.WITHDRAW_WITH_EXTRA
if (getters.hasEnabledLightProxy) { if (getters.hasEnabledLightProxy) {
action = ACTION.WITHDRAW action = ACTION.WITHDRAW
} }
if (Number(netId) === 10) { if (getters.isOptimismConnected) {
action = ACTION.OP_WITHDRAW action = ACTION.OP_WITHDRAW
} }
if (Number(netId) === 42161) { if (getters.isArbitrumConnected) {
action = ACTION.ARB_WITHDRAW action = ACTION.ARB_WITHDRAW
} }
@ -169,7 +168,14 @@ const getters = {
networkFee: (state, getters, rootState, rootGetters) => { networkFee: (state, getters, rootState, rootGetters) => {
const gasPrice = rootGetters['gasPrices/fastGasPrice'] const gasPrice = rootGetters['gasPrices/fastGasPrice']
return toBN(gasPrice).mul(toBN(getters.withdrawGas)) const networkFee = toBN(gasPrice).mul(toBN(getters.withdrawGas))
if (getters.isOptimismConnected) {
const l1Fee = rootGetters['gasPrices/l1Fee']
return networkFee.add(toBN(l1Fee))
}
return networkFee
}, },
relayerFee: (state, getters, rootState, rootGetters) => { relayerFee: (state, getters, rootState, rootGetters) => {
const { currency, amount } = rootState.application.selectedStatistic const { currency, amount } = rootState.application.selectedStatistic
@ -245,6 +251,14 @@ const getters = {
}, },
hasEnabledLightProxy: (state, getters, rootState, rootGetters) => { hasEnabledLightProxy: (state, getters, rootState, rootGetters) => {
return Boolean(rootGetters['metamask/networkConfig']['tornado-proxy-light.contract.tornadocash.eth']) return Boolean(rootGetters['metamask/networkConfig']['tornado-proxy-light.contract.tornadocash.eth'])
},
isOptimismConnected: (state, getters, rootState, rootGetters) => {
const netId = rootGetters['metamask/netId']
return Number(netId) === 10
},
isArbitrumConnected: (state, getters, rootState, rootGetters) => {
const netId = rootGetters['metamask/netId']
return Number(netId) === 42161
} }
} }

@ -1,7 +1,13 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import Web3 from 'web3'
import { GasPriceOracle } from 'gas-price-oracle' import { GasPriceOracle } from 'gas-price-oracle'
import { serialize } from '@ethersproject/transactions'
import { toHex, toWei, toBN, fromWei } from 'web3-utils' import { toHex, toWei, toBN, fromWei } from 'web3-utils'
import networkConfig from '@/networkConfig'
import OvmGasPriceOracleABI from '@/abis/OvmGasPriceOracle.abi.json'
import { DUMMY_NONCE, DUMMY_WITHDRAW_DATA } from '@/constants/variables'
export const state = () => { export const state = () => {
return { return {
oracle: { oracle: {
@ -31,11 +37,26 @@ export const state = () => {
maxFeePerGas: 9, maxFeePerGas: 9,
maxPriorityFeePerGas: 1 maxPriorityFeePerGas: 1
} }
} },
l1Fee: '0'
} }
} }
export const getters = { export const getters = {
ovmGasPriceOracleContract: (state, getters, rootState) => ({ netId }) => {
const config = networkConfig[`netId${netId}`]
const { url } = rootState.settings[`netId${netId}`].rpc
const address = config.ovmGasPriceOracleContract
if (address) {
const web3 = new Web3(url)
return new web3.eth.Contract(OvmGasPriceOracleABI, address)
}
return null
},
l1Fee: (state) => {
return state.l1Fee
},
oracle: (state, getters, rootState, rootGetters) => { oracle: (state, getters, rootState, rootGetters) => {
const netId = Number(rootGetters['metamask/netId']) const netId = Number(rootGetters['metamask/netId'])
const { gasPrices } = rootGetters['metamask/networkConfig'] const { gasPrices } = rootGetters['metamask/networkConfig']
@ -108,6 +129,9 @@ export const mutations = {
this._vm.$set(state.eip, 'fast', fast) this._vm.$set(state.eip, 'fast', fast)
this._vm.$set(state.eip, 'standard', standard) this._vm.$set(state.eip, 'standard', standard)
this._vm.$set(state.eip, 'low', low) this._vm.$set(state.eip, 'low', low)
},
SAVE_L1_FEE(state, l1Fee) {
state.l1Fee = l1Fee
} }
} }
@ -124,6 +148,8 @@ export const actions = {
commit('SAVE_ORACLE_GAS_PRICES', gas) commit('SAVE_ORACLE_GAS_PRICES', gas)
} }
await dispatch('fetchL1Fee')
setTimeout(() => dispatch('fetchGasPrice'), 1000 * pollInterval) setTimeout(() => dispatch('fetchGasPrice'), 1000 * pollInterval)
} catch (e) { } catch (e) {
console.error('fetchGasPrice', e) console.error('fetchGasPrice', e)
@ -187,5 +213,36 @@ export const actions = {
setDefault({ commit, rootGetters }) { setDefault({ commit, rootGetters }) {
const { gasPrices } = rootGetters['metamask/networkConfig'] const { gasPrices } = rootGetters['metamask/networkConfig']
commit('SAVE_ORACLE_GAS_PRICES', gasPrices) commit('SAVE_ORACLE_GAS_PRICES', gasPrices)
},
async fetchL1Fee({ commit, getters, dispatch, rootGetters }) {
const netId = rootGetters['metamask/netId']
const isOptimismConnected = rootGetters['application/isOptimismConnected']
const oracleInstance = getters.ovmGasPriceOracleContract({ netId })
if (isOptimismConnected && oracleInstance) {
try {
const gasLimit = rootGetters['application/withdrawGas']
const tornadoProxyInstance = rootGetters['application/tornadoProxyContract']({ netId })
const gasPrice = getters.fastGasPrice
const tx = serialize({
type: 0,
gasLimit,
gasPrice,
chainId: netId,
nonce: DUMMY_NONCE,
data: DUMMY_WITHDRAW_DATA,
to: tornadoProxyInstance._address
})
const l1Fee = await oracleInstance.methods.getL1Fee(tx).call()
commit('SAVE_L1_FEE', l1Fee)
} catch (err) {
console.error('fetchL1Fee has error:', err.message)
}
}
} }
} }