feat: l1 gas price estimation when placing l2 transaction
This commit is contained in:
parent
1a2880b365
commit
98c3be55b9
|
@ -0,0 +1,24 @@
|
||||||
|
package gaspriceoracle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
||||||
|
wallet_common "github.com/status-im/status-go/services/wallet/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrorNotAvailableOnChainID = errors.New("not available for chainID")
|
||||||
|
|
||||||
|
var contractAddressByChainID = map[uint64]common.Address{
|
||||||
|
wallet_common.OptimismMainnet: common.HexToAddress("0x8527c030424728cF93E72bDbf7663281A44Eeb22"),
|
||||||
|
wallet_common.OptimismSepolia: common.HexToAddress("0x5230210c2b4995FD5084b0F5FD0D7457aebb5010"),
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContractAddress(chainID uint64) (common.Address, error) {
|
||||||
|
addr, exists := contractAddressByChainID[chainID]
|
||||||
|
if !exists {
|
||||||
|
return *new(common.Address), ErrorNotAvailableOnChainID
|
||||||
|
}
|
||||||
|
return addr, nil
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
package gaspriceoracle
|
||||||
|
|
||||||
|
//go:generate abigen -abi gaspriceoracle.abi -pkg gaspriceoracle -out gaspriceoracle.go
|
|
@ -0,0 +1,316 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"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": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "ScalarUpdated",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "admin",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "target",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes",
|
||||||
|
"name": "data",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "adminCall",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": [],
|
||||||
|
"name": "getAdmin",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "adminAddress",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes",
|
||||||
|
"name": "initPayload",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "init",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes4",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"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": "scalar",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "adminAddress",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setAdmin",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
File diff suppressed because it is too large
Load Diff
|
@ -106,4 +106,5 @@ type Bridge interface {
|
||||||
Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error)
|
Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error)
|
||||||
GetContractAddress(network *params.Network, token *token.Token) *common.Address
|
GetContractAddress(network *params.Network, token *token.Token) *common.Address
|
||||||
BuildTransaction(sendArgs *TransactionBridge) (*ethTypes.Transaction, error)
|
BuildTransaction(sendArgs *TransactionBridge) (*ethTypes.Transaction, error)
|
||||||
|
BuildTx(network *params.Network, fromAddress common.Address, toAddress common.Address, token *token.Token, amountIn *big.Int) (*ethTypes.Transaction, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,6 +288,26 @@ func (s *CBridge) EstimateGas(fromNetwork *params.Network, toNetwork *params.Net
|
||||||
return uint64(increasedEstimation), nil
|
return uint64(increasedEstimation), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *CBridge) BuildTx(network *params.Network, fromAddress common.Address, toAddress common.Address, token *token.Token, amountIn *big.Int) (*ethTypes.Transaction, error) {
|
||||||
|
toAddr := types.Address(toAddress)
|
||||||
|
sendArgs := &TransactionBridge{
|
||||||
|
CbridgeTx: &CBridgeTxArgs{
|
||||||
|
SendTxArgs: transactions.SendTxArgs{
|
||||||
|
From: types.Address(fromAddress),
|
||||||
|
To: &toAddr,
|
||||||
|
Value: (*hexutil.Big)(amountIn),
|
||||||
|
Data: types.HexBytes("0x0"),
|
||||||
|
},
|
||||||
|
ChainID: network.ChainID,
|
||||||
|
Symbol: token.Symbol,
|
||||||
|
Recipient: toAddress,
|
||||||
|
Amount: (*hexutil.Big)(amountIn),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.BuildTransaction(sendArgs)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *CBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
|
func (s *CBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
|
||||||
transferConfig, err := s.getTransferConfig(network.IsTest)
|
transferConfig, err := s.getTransferConfig(network.IsTest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -101,6 +101,25 @@ func (s *ERC1155TransferBridge) EstimateGas(fromNetwork *params.Network, toNetwo
|
||||||
return uint64(increasedEstimation), nil
|
return uint64(increasedEstimation), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ERC1155TransferBridge) BuildTx(network *params.Network, fromAddress common.Address, toAddress common.Address, token *token.Token, amountIn *big.Int) (*ethTypes.Transaction, error) {
|
||||||
|
toAddr := types.Address(toAddress)
|
||||||
|
sendArgs := &TransactionBridge{
|
||||||
|
ERC1155TransferTx: &ERC1155TransferTxArgs{
|
||||||
|
SendTxArgs: transactions.SendTxArgs{
|
||||||
|
From: types.Address(fromAddress),
|
||||||
|
To: &toAddr,
|
||||||
|
Value: (*hexutil.Big)(amountIn),
|
||||||
|
Data: types.HexBytes("0x0"),
|
||||||
|
},
|
||||||
|
TokenID: (*hexutil.Big)(big.NewInt(0)),
|
||||||
|
Recipient: toAddress,
|
||||||
|
Amount: (*hexutil.Big)(amountIn),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.BuildTransaction(sendArgs)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ERC1155TransferBridge) sendOrBuild(sendArgs *TransactionBridge, signerFn bind.SignerFn) (tx *ethTypes.Transaction, err error) {
|
func (s *ERC1155TransferBridge) sendOrBuild(sendArgs *TransactionBridge, signerFn bind.SignerFn) (tx *ethTypes.Transaction, err error) {
|
||||||
ethClient, err := s.rpcClient.EthClient(sendArgs.ChainID)
|
ethClient, err := s.rpcClient.EthClient(sendArgs.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -98,6 +98,24 @@ func (s *ERC721TransferBridge) EstimateGas(fromNetwork *params.Network, toNetwor
|
||||||
return uint64(increasedEstimation), nil
|
return uint64(increasedEstimation), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ERC721TransferBridge) BuildTx(network *params.Network, fromAddress common.Address, toAddress common.Address, token *token.Token, amountIn *big.Int) (*ethTypes.Transaction, error) {
|
||||||
|
toAddr := types.Address(toAddress)
|
||||||
|
sendArgs := &TransactionBridge{
|
||||||
|
ERC721TransferTx: &ERC721TransferTxArgs{
|
||||||
|
SendTxArgs: transactions.SendTxArgs{
|
||||||
|
From: types.Address(fromAddress),
|
||||||
|
To: &toAddr,
|
||||||
|
Value: (*hexutil.Big)(amountIn),
|
||||||
|
Data: types.HexBytes("0x0"),
|
||||||
|
},
|
||||||
|
TokenID: (*hexutil.Big)(big.NewInt(0)),
|
||||||
|
Recipient: toAddress,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.BuildTransaction(sendArgs)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ERC721TransferBridge) sendOrBuild(sendArgs *TransactionBridge, signerFn bind.SignerFn) (tx *ethTypes.Transaction, err error) {
|
func (s *ERC721TransferBridge) sendOrBuild(sendArgs *TransactionBridge, signerFn bind.SignerFn) (tx *ethTypes.Transaction, err error) {
|
||||||
ethClient, err := s.rpcClient.EthClient(sendArgs.ChainID)
|
ethClient, err := s.rpcClient.EthClient(sendArgs.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -215,6 +215,26 @@ func (h *HopBridge) EstimateGas(fromNetwork *params.Network, toNetwork *params.N
|
||||||
return uint64(increasedEstimation), nil
|
return uint64(increasedEstimation), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *HopBridge) BuildTx(network *params.Network, fromAddress common.Address, toAddress common.Address, token *token.Token, amountIn *big.Int) (*ethTypes.Transaction, error) {
|
||||||
|
toAddr := types.Address(toAddress)
|
||||||
|
sendArgs := &TransactionBridge{
|
||||||
|
HopTx: &HopTxArgs{
|
||||||
|
SendTxArgs: transactions.SendTxArgs{
|
||||||
|
From: types.Address(fromAddress),
|
||||||
|
To: &toAddr,
|
||||||
|
Value: (*hexutil.Big)(amountIn),
|
||||||
|
Data: types.HexBytes("0x0"),
|
||||||
|
},
|
||||||
|
ChainID: network.ChainID,
|
||||||
|
Symbol: token.Symbol,
|
||||||
|
Recipient: toAddress,
|
||||||
|
Amount: (*hexutil.Big)(amountIn),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.BuildTransaction(sendArgs)
|
||||||
|
}
|
||||||
|
|
||||||
func (h *HopBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
|
func (h *HopBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
|
||||||
var address common.Address
|
var address common.Address
|
||||||
if network.Layer == 1 {
|
if network.Layer == 1 {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
ethTypes "github.com/ethereum/go-ethereum/core/types"
|
ethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/status-im/status-go/account"
|
"github.com/status-im/status-go/account"
|
||||||
"github.com/status-im/status-go/contracts/ierc20"
|
"github.com/status-im/status-go/contracts/ierc20"
|
||||||
|
@ -84,6 +85,21 @@ func (s *TransferBridge) EstimateGas(fromNetwork *params.Network, toNetwork *par
|
||||||
return uint64(increasedEstimation), nil
|
return uint64(increasedEstimation), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TransferBridge) BuildTx(network *params.Network, fromAddress common.Address, toAddress common.Address, token *token.Token, amountIn *big.Int) (*ethTypes.Transaction, error) {
|
||||||
|
toAddr := types.Address(toAddress)
|
||||||
|
sendArgs := &TransactionBridge{
|
||||||
|
TransferTx: &transactions.SendTxArgs{
|
||||||
|
From: types.Address(fromAddress),
|
||||||
|
To: &toAddr,
|
||||||
|
Value: (*hexutil.Big)(amountIn),
|
||||||
|
Data: types.HexBytes("0x0"),
|
||||||
|
},
|
||||||
|
ChainID: network.ChainID,
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.BuildTransaction(sendArgs)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TransferBridge) Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error) {
|
func (s *TransferBridge) Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error) {
|
||||||
return s.transactor.SendTransactionWithChainID(sendArgs.ChainID, *sendArgs.TransferTx, verifiedAccount)
|
return s.transactor.SendTransactionWithChainID(sendArgs.ChainID, *sendArgs.TransferTx, verifiedAccount)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,11 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
|
ethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
gaspriceoracle "github.com/status-im/status-go/contracts/gas-price-oracle"
|
||||||
"github.com/status-im/status-go/rpc"
|
"github.com/status-im/status-go/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +30,7 @@ type SuggestedFees struct {
|
||||||
MaxFeePerGasLow *big.Float `json:"maxFeePerGasLow"`
|
MaxFeePerGasLow *big.Float `json:"maxFeePerGasLow"`
|
||||||
MaxFeePerGasMedium *big.Float `json:"maxFeePerGasMedium"`
|
MaxFeePerGasMedium *big.Float `json:"maxFeePerGasMedium"`
|
||||||
MaxFeePerGasHigh *big.Float `json:"maxFeePerGasHigh"`
|
MaxFeePerGasHigh *big.Float `json:"maxFeePerGasHigh"`
|
||||||
|
L1GasFee *big.Float `json:"l1GasFee"`
|
||||||
EIP1559Enabled bool `json:"eip1559Enabled"`
|
EIP1559Enabled bool `json:"eip1559Enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,3 +255,35 @@ func (f *FeeManager) getFeeHistorySorted(chainID uint64) ([]*big.Int, error) {
|
||||||
sort.Slice(fees, func(i, j int) bool { return fees[i].Cmp(fees[j]) < 0 })
|
sort.Slice(fees, func(i, j int) bool { return fees[i].Cmp(fees[j]) < 0 })
|
||||||
return fees, nil
|
return fees, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FeeManager) getL1Fee(ctx context.Context, chainID uint64, tx *ethTypes.Transaction) (uint64, error) {
|
||||||
|
|
||||||
|
ethClient, err := f.RPCClient.EthClient(chainID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contractAddress, err := gaspriceoracle.ContractAddress(chainID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contract, err := gaspriceoracle.NewGaspriceoracleCaller(contractAddress, ethClient)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
callOpt := &bind.CallOpts{}
|
||||||
|
|
||||||
|
data, err := tx.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := contract.GetL1Fee(callOpt, data)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Uint64(), nil
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/status-im/status-go/contracts"
|
"github.com/status-im/status-go/contracts"
|
||||||
|
gaspriceoracle "github.com/status-im/status-go/contracts/gas-price-oracle"
|
||||||
"github.com/status-im/status-go/contracts/ierc20"
|
"github.com/status-im/status-go/contracts/ierc20"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
|
@ -450,27 +451,28 @@ type Router struct {
|
||||||
rpcClient *rpc.Client
|
rpcClient *rpc.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) requireApproval(ctx context.Context, sendType SendType, bridge bridge.Bridge, account common.Address, network *params.Network, token *token.Token, amountIn *big.Int) (bool, *big.Int, uint64, *common.Address, error) {
|
func (r *Router) requireApproval(ctx context.Context, sendType SendType, bridge bridge.Bridge, account common.Address, network *params.Network, token *token.Token, amountIn *big.Int) (
|
||||||
|
bool, *big.Int, uint64, uint64, *common.Address, error) {
|
||||||
if sendType.IsCollectiblesTransfer() {
|
if sendType.IsCollectiblesTransfer() {
|
||||||
return false, nil, 0, nil, nil
|
return false, nil, 0, 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if token.IsNative() {
|
if token.IsNative() {
|
||||||
return false, nil, 0, nil, nil
|
return false, nil, 0, 0, nil, nil
|
||||||
}
|
}
|
||||||
contractMaker, err := contracts.NewContractMaker(r.rpcClient)
|
contractMaker, err := contracts.NewContractMaker(r.rpcClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, 0, nil, err
|
return false, nil, 0, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bridgeAddress := bridge.GetContractAddress(network, token)
|
bridgeAddress := bridge.GetContractAddress(network, token)
|
||||||
if bridgeAddress == nil {
|
if bridgeAddress == nil {
|
||||||
return false, nil, 0, nil, nil
|
return false, nil, 0, 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
contract, err := contractMaker.NewERC20(network.ChainID, token.Address)
|
contract, err := contractMaker.NewERC20(network.ChainID, token.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, 0, nil, err
|
return false, nil, 0, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
allowance, err := contract.Allowance(&bind.CallOpts{
|
allowance, err := contract.Allowance(&bind.CallOpts{
|
||||||
|
@ -478,26 +480,26 @@ func (r *Router) requireApproval(ctx context.Context, sendType SendType, bridge
|
||||||
}, account, *bridgeAddress)
|
}, account, *bridgeAddress)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, 0, nil, err
|
return false, nil, 0, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if allowance.Cmp(amountIn) >= 0 {
|
if allowance.Cmp(amountIn) >= 0 {
|
||||||
return false, nil, 0, nil, nil
|
return false, nil, 0, 0, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ethClient, err := r.rpcClient.EthClient(network.ChainID)
|
ethClient, err := r.rpcClient.EthClient(network.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, 0, nil, err
|
return false, nil, 0, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
erc20ABI, err := abi.JSON(strings.NewReader(ierc20.IERC20ABI))
|
erc20ABI, err := abi.JSON(strings.NewReader(ierc20.IERC20ABI))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, 0, nil, err
|
return false, nil, 0, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := erc20ABI.Pack("approve", bridgeAddress, amountIn)
|
data, err := erc20ABI.Pack("approve", bridgeAddress, amountIn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, 0, nil, err
|
return false, nil, 0, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
estimate, err := ethClient.EstimateGas(context.Background(), ethereum.CallMsg{
|
estimate, err := ethClient.EstimateGas(context.Background(), ethereum.CallMsg{
|
||||||
|
@ -507,11 +509,25 @@ func (r *Router) requireApproval(ctx context.Context, sendType SendType, bridge
|
||||||
Data: data,
|
Data: data,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, 0, nil, err
|
return false, nil, 0, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, amountIn, estimate, bridgeAddress, nil
|
// fetching l1 fee
|
||||||
|
oracleContractAddress, err := gaspriceoracle.ContractAddress(network.ChainID)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, 0, 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
oracleContract, err := gaspriceoracle.NewGaspriceoracleCaller(oracleContractAddress, ethClient)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, 0, 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
callOpt := &bind.CallOpts{}
|
||||||
|
|
||||||
|
l1Fee, _ := oracleContract.GetL1Fee(callOpt, data)
|
||||||
|
|
||||||
|
return true, amountIn, estimate, l1Fee.Uint64(), bridgeAddress, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) getBalance(ctx context.Context, network *params.Network, token *token.Token, account common.Address) (*big.Int, error) {
|
func (r *Router) getBalance(ctx context.Context, network *params.Network, token *token.Token, account common.Address) (*big.Int, error) {
|
||||||
|
@ -692,31 +708,45 @@ func (r *Router) suggestedRoutes(
|
||||||
gasLimit = sendType.EstimateGas(r.s, network, addrFrom, tokenID)
|
gasLimit = sendType.EstimateGas(r.s, network, addrFrom, tokenID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
approvalRequired, approvalAmountRequired, approvalGasLimit, l1ApprovalFee, approvalContractAddress, err := r.requireApproval(ctx, sendType, bridge, addrFrom, network, token, amountIn)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := bridge.BuildTx(network, addrTo, addrFrom, token, amountIn)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
l1GasFeeWei, _ := r.s.feesManager.getL1Fee(ctx, network.ChainID, tx)
|
||||||
|
l1GasFeeWei += l1ApprovalFee
|
||||||
|
gasFees.L1GasFee = weiToGwei(big.NewInt(int64(l1GasFeeWei)))
|
||||||
|
|
||||||
requiredNativeBalance := new(big.Int).Mul(gweiToWei(maxFees), big.NewInt(int64(gasLimit)))
|
requiredNativeBalance := new(big.Int).Mul(gweiToWei(maxFees), big.NewInt(int64(gasLimit)))
|
||||||
|
requiredNativeBalance.Add(requiredNativeBalance, new(big.Int).Mul(gweiToWei(maxFees), big.NewInt(int64(approvalGasLimit))))
|
||||||
|
requiredNativeBalance.Add(requiredNativeBalance, big.NewInt(int64(l1GasFeeWei))) // add l1Fee to requiredNativeBalance, in case of L1 chain l1Fee is 0
|
||||||
|
|
||||||
|
if nativeBalance.Cmp(requiredNativeBalance) <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Removed the required fees from maxAMount in case of native token tx
|
// Removed the required fees from maxAMount in case of native token tx
|
||||||
if token.IsNative() {
|
if token.IsNative() {
|
||||||
maxAmountIn = (*hexutil.Big)(new(big.Int).Sub(maxAmountIn.ToInt(), requiredNativeBalance))
|
maxAmountIn = (*hexutil.Big)(new(big.Int).Sub(maxAmountIn.ToInt(), requiredNativeBalance))
|
||||||
}
|
}
|
||||||
if nativeBalance.Cmp(requiredNativeBalance) <= 0 {
|
|
||||||
continue
|
ethPrice := big.NewFloat(prices["ETH"])
|
||||||
}
|
|
||||||
approvalRequired, approvalAmountRequired, approvalGasLimit, approvalContractAddress, err := r.requireApproval(ctx, sendType, bridge, addrFrom, network, token, amountIn)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
approvalGasFees := new(big.Float).Mul(gweiToEth(maxFees), big.NewFloat((float64(approvalGasLimit))))
|
approvalGasFees := new(big.Float).Mul(gweiToEth(maxFees), big.NewFloat((float64(approvalGasLimit))))
|
||||||
|
|
||||||
approvalGasCost := new(big.Float)
|
approvalGasCost := new(big.Float)
|
||||||
approvalGasCost.Mul(
|
approvalGasCost.Mul(approvalGasFees, ethPrice)
|
||||||
approvalGasFees,
|
|
||||||
big.NewFloat(prices["ETH"]),
|
l1GasCost := new(big.Float)
|
||||||
)
|
l1GasCost.Mul(gasFees.L1GasFee, ethPrice)
|
||||||
|
|
||||||
gasCost := new(big.Float)
|
gasCost := new(big.Float)
|
||||||
gasCost.Mul(
|
gasCost.Mul(new(big.Float).Mul(gweiToEth(maxFees), big.NewFloat(float64(gasLimit))), ethPrice)
|
||||||
new(big.Float).Mul(gweiToEth(maxFees), big.NewFloat((float64(gasLimit)))),
|
|
||||||
big.NewFloat(prices["ETH"]),
|
|
||||||
)
|
|
||||||
|
|
||||||
tokenFeesAsFloat := new(big.Float).Quo(
|
tokenFeesAsFloat := new(big.Float).Quo(
|
||||||
new(big.Float).SetInt(tokenFees),
|
new(big.Float).SetInt(tokenFees),
|
||||||
|
@ -728,6 +758,7 @@ func (r *Router) suggestedRoutes(
|
||||||
cost := new(big.Float)
|
cost := new(big.Float)
|
||||||
cost.Add(tokenCost, gasCost)
|
cost.Add(tokenCost, gasCost)
|
||||||
cost.Add(cost, approvalGasCost)
|
cost.Add(cost, approvalGasCost)
|
||||||
|
cost.Add(cost, l1GasCost)
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
candidates = append(candidates, &Path{
|
candidates = append(candidates, &Path{
|
||||||
BridgeName: bridge.Name(),
|
BridgeName: bridge.Name(),
|
||||||
|
|
Loading…
Reference in New Issue