fix: estimate gas function resoved that it uses real network estimation instead of hardcoded value
This commit is contained in:
parent
4fddcb54ff
commit
05baec8bec
|
@ -451,7 +451,8 @@ func (api *API) GetTransactionEstimatedTime(ctx context.Context, chainID uint64,
|
|||
func (api *API) GetSuggestedRoutes(
|
||||
ctx context.Context,
|
||||
sendType SendType,
|
||||
account common.Address,
|
||||
addrFrom common.Address,
|
||||
addrTo common.Address,
|
||||
amountIn *hexutil.Big,
|
||||
tokenID string,
|
||||
disabledFromChainIDs,
|
||||
|
@ -461,7 +462,8 @@ func (api *API) GetSuggestedRoutes(
|
|||
fromLockedAmount map[uint64]*hexutil.Big,
|
||||
) (*SuggestedRoutes, error) {
|
||||
log.Debug("call to GetSuggestedRoutes")
|
||||
return api.router.suggestedRoutes(ctx, sendType, account, amountIn.ToInt(), tokenID, disabledFromChainIDs, disabledToChaindIDs, preferedChainIDs, gasFeeMode, fromLockedAmount)
|
||||
return api.router.suggestedRoutes(ctx, sendType, addrFrom, addrTo, amountIn.ToInt(), tokenID, disabledFromChainIDs,
|
||||
disabledToChaindIDs, preferedChainIDs, gasFeeMode, fromLockedAmount)
|
||||
}
|
||||
|
||||
// Generates addresses for the provided paths, response doesn't include `HasActivity` value (if you need it check `GetAddressDetails` function)
|
||||
|
|
|
@ -14,6 +14,8 @@ import (
|
|||
"github.com/status-im/status-go/transactions"
|
||||
)
|
||||
|
||||
const IncreaseEstimatedGasFactor = 1.1
|
||||
|
||||
func getSigner(chainID uint64, from types.Address, verifiedAccount *account.SelectedExtKey) bind.SignerFn {
|
||||
return func(addr common.Address, tx *ethTypes.Transaction) (*ethTypes.Transaction, error) {
|
||||
s := ethTypes.NewLondonSigner(new(big.Int).SetUint64(chainID))
|
||||
|
@ -90,7 +92,7 @@ type Bridge interface {
|
|||
Name() string
|
||||
Can(from *params.Network, to *params.Network, token *token.Token, balance *big.Int) (bool, error)
|
||||
CalculateFees(from, to *params.Network, token *token.Token, amountIn *big.Int, nativeTokenPrice, tokenPrice float64, gasPrice *big.Float) (*big.Int, *big.Int, error)
|
||||
EstimateGas(from *params.Network, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error)
|
||||
EstimateGas(fromNetwork *params.Network, toNetwork *params.Network, from common.Address, to common.Address, token *token.Token, amountIn *big.Int) (uint64, error)
|
||||
CalculateAmountOut(from, to *params.Network, amountIn *big.Int, symbol string) (*big.Int, error)
|
||||
Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error)
|
||||
GetContractAddress(network *params.Network, token *token.Token) *common.Address
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
@ -217,13 +221,71 @@ func (s *CBridge) CalculateFees(from, to *params.Network, token *token.Token, am
|
|||
return big.NewInt(0), new(big.Int).Add(baseFee, percFee), nil
|
||||
}
|
||||
|
||||
func (s *CBridge) EstimateGas(from, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
|
||||
// TODO: replace by estimate function
|
||||
if token.IsNative() {
|
||||
return 22000, nil // default gas limit for eth transaction
|
||||
func (s *CBridge) EstimateGas(fromNetwork *params.Network, toNetwork *params.Network, from common.Address, to common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
|
||||
var input []byte
|
||||
value := new(big.Int)
|
||||
|
||||
abi, err := abi.JSON(strings.NewReader(celer.CelerABI))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return 200000, nil //default gas limit for erc20 transaction
|
||||
if token.IsNative() {
|
||||
input, err = abi.Pack("sendNative",
|
||||
to,
|
||||
amountIn,
|
||||
toNetwork.ChainID,
|
||||
uint64(time.Now().UnixMilli()),
|
||||
500,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
input, err = abi.Pack("send",
|
||||
to,
|
||||
token.Address,
|
||||
amountIn,
|
||||
toNetwork.ChainID,
|
||||
uint64(time.Now().UnixMilli()),
|
||||
500,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
contractAddress := s.GetContractAddress(fromNetwork, nil)
|
||||
if contractAddress == nil {
|
||||
return 0, errors.New("contract not found")
|
||||
}
|
||||
|
||||
ethClient, err := s.rpcClient.EthClient(fromNetwork.ChainID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if code, err := ethClient.PendingCodeAt(ctx, *contractAddress); err != nil {
|
||||
return 0, err
|
||||
} else if len(code) == 0 {
|
||||
return 0, bind.ErrNoCode
|
||||
}
|
||||
|
||||
msg := ethereum.CallMsg{
|
||||
From: from,
|
||||
To: contractAddress,
|
||||
Value: value,
|
||||
Data: input,
|
||||
}
|
||||
|
||||
estimation, err := ethClient.EstimateGas(ctx, msg)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor
|
||||
return uint64(increasedEstimation), nil
|
||||
}
|
||||
|
||||
func (s *CBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
@ -43,37 +47,52 @@ func (s *ERC721TransferBridge) CalculateFees(from, to *params.Network, token *to
|
|||
return big.NewInt(0), big.NewInt(0), nil
|
||||
}
|
||||
|
||||
func (s *ERC721TransferBridge) EstimateGas(from, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
|
||||
// ethClient, err := s.rpcClient.EthClient(from.ChainID)
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// collectiblesABI, err := abi.JSON(strings.NewReader(collectibles.CollectiblesABI))
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
func (s *ERC721TransferBridge) EstimateGas(fromNetwork *params.Network, toNetwork *params.Network, from common.Address, to common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
|
||||
ethClient, err := s.rpcClient.EthClient(fromNetwork.ChainID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// toAddress := common.HexToAddress("0x0")
|
||||
// tokenID, success := new(big.Int).SetString(token.Symbol, 10)
|
||||
// if !success {
|
||||
// return 0, err
|
||||
// }
|
||||
var input []byte
|
||||
value := new(big.Int)
|
||||
|
||||
// data, err := collectiblesABI.Pack("safeTransferFrom", account, toAddress, tokenID)
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// estimate, err := ethClient.EstimateGas(context.Background(), ethereum.CallMsg{
|
||||
// From: account,
|
||||
// To: &toAddress,
|
||||
// Value: big.NewInt(0),
|
||||
// Data: data,
|
||||
// })
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// return estimate + 1000, nil
|
||||
return 80000, nil
|
||||
contractAddress := to
|
||||
|
||||
abi, err := abi.JSON(strings.NewReader(collectibles.CollectiblesMetaData.ABI))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
input, err = abi.Pack("safeTransferFrom",
|
||||
from,
|
||||
to,
|
||||
new(big.Int))
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if code, err := ethClient.PendingCodeAt(ctx, contractAddress); err != nil {
|
||||
return 0, err
|
||||
} else if len(code) == 0 {
|
||||
return 0, bind.ErrNoCode
|
||||
}
|
||||
|
||||
msg := ethereum.CallMsg{
|
||||
From: from,
|
||||
To: &contractAddress,
|
||||
Value: value,
|
||||
Data: input,
|
||||
}
|
||||
|
||||
estimation, err := ethClient.EstimateGas(ctx, msg)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor
|
||||
return uint64(increasedEstimation), nil
|
||||
}
|
||||
|
||||
func (s *ERC721TransferBridge) sendOrBuild(sendArgs *TransactionBridge, signerFn bind.SignerFn) (tx *ethTypes.Transaction, err error) {
|
||||
|
|
|
@ -2,10 +2,14 @@ package bridge
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
@ -13,6 +17,8 @@ import (
|
|||
"github.com/status-im/status-go/account"
|
||||
"github.com/status-im/status-go/contracts"
|
||||
"github.com/status-im/status-go/contracts/hop"
|
||||
hopBridge "github.com/status-im/status-go/contracts/hop/bridge"
|
||||
hopWrapper "github.com/status-im/status-go/contracts/hop/wrapper"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/params"
|
||||
"github.com/status-im/status-go/rpc"
|
||||
|
@ -126,41 +132,87 @@ func (h *HopBridge) Can(from, to *params.Network, token *token.Token, balance *b
|
|||
return true, nil
|
||||
}
|
||||
|
||||
func (h *HopBridge) EstimateGas(from, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
|
||||
// TODO: find why this doesn't work
|
||||
// ethClient, err := s.contractMaker.RPCClient.EthClient(from.ChainID)
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// zero := common.HexToAddress("0x0")
|
||||
// zeroInt := big.NewInt(0)
|
||||
// var data []byte
|
||||
// if from.Layer == 1 {
|
||||
// bridgeABI, err := abi.JSON(strings.NewReader(hopBridge.HopBridgeABI))
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// data, err = bridgeABI.Pack("sendToL2", big.NewInt(int64(to.ChainID)), zero, amountIn, zeroInt, zeroInt, zero, zeroInt)
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// } else {
|
||||
// wrapperABI, err := abi.JSON(strings.NewReader(hopWrapper.HopWrapperABI))
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// data, err = wrapperABI.Pack("swapAndSend", big.NewInt(int64(to.ChainID)), zero, amountIn, zeroInt, zeroInt, zeroInt, zeroInt, zeroInt)
|
||||
// if err != nil {
|
||||
// return 0, err
|
||||
// }
|
||||
// }
|
||||
// estimate, err := ethClient.EstimateGas(context.Background(), ethereum.CallMsg{
|
||||
// From: zero,
|
||||
// To: &token.Address,
|
||||
// Value: big.NewInt(0),
|
||||
// Data: data,
|
||||
// })
|
||||
return 500000 + 1000, nil
|
||||
func (h *HopBridge) EstimateGas(fromNetwork *params.Network, toNetwork *params.Network, from common.Address, to common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
|
||||
var input []byte
|
||||
value := new(big.Int)
|
||||
|
||||
now := time.Now()
|
||||
deadline := big.NewInt(now.Unix() + 604800)
|
||||
|
||||
if token.IsNative() {
|
||||
value = amountIn
|
||||
}
|
||||
|
||||
contractAddress := h.GetContractAddress(fromNetwork, token)
|
||||
if contractAddress == nil {
|
||||
return 0, errors.New("contract not found")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if fromNetwork.Layer == 1 {
|
||||
ABI, err := abi.JSON(strings.NewReader(hopBridge.HopBridgeABI))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
input, err = ABI.Pack("sendToL2",
|
||||
big.NewInt(int64(toNetwork.ChainID)),
|
||||
to,
|
||||
amountIn,
|
||||
big.NewInt(0),
|
||||
deadline,
|
||||
common.HexToAddress("0x0"),
|
||||
big.NewInt(0))
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
ABI, err := abi.JSON(strings.NewReader(hopWrapper.HopWrapperABI))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
input, err = ABI.Pack("swapAndSend",
|
||||
big.NewInt(int64(toNetwork.ChainID)),
|
||||
to,
|
||||
amountIn,
|
||||
big.NewInt(0),
|
||||
big.NewInt(0),
|
||||
deadline,
|
||||
big.NewInt(0),
|
||||
deadline)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
ethClient, err := h.contractMaker.RPCClient.EthClient(fromNetwork.ChainID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if code, err := ethClient.PendingCodeAt(ctx, *contractAddress); err != nil {
|
||||
return 0, err
|
||||
} else if len(code) == 0 {
|
||||
return 0, bind.ErrNoCode
|
||||
}
|
||||
|
||||
msg := ethereum.CallMsg{
|
||||
From: from,
|
||||
To: contractAddress,
|
||||
Value: value,
|
||||
Data: input,
|
||||
}
|
||||
|
||||
estimation, err := ethClient.EstimateGas(ctx, msg)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor
|
||||
return uint64(increasedEstimation), nil
|
||||
}
|
||||
|
||||
func (h *HopBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
|
||||
|
|
|
@ -32,13 +32,13 @@ func (s *TransferBridge) CalculateFees(from, to *params.Network, token *token.To
|
|||
return big.NewInt(0), big.NewInt(0), nil
|
||||
}
|
||||
|
||||
func (s *TransferBridge) EstimateGas(from, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
|
||||
// TODO: replace by estimate function
|
||||
if token.IsNative() {
|
||||
return 22000, nil // default gas limit for eth transaction
|
||||
func (s *TransferBridge) EstimateGas(fromNetwork *params.Network, toNetwork *params.Network, from common.Address, to common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
|
||||
estimation, err := s.transactor.EstimateGas(fromNetwork, from, to, amountIn, []byte("eth_sendRawTransaction"))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return 200000, nil //default gas limit for erc20 transaction
|
||||
increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor
|
||||
return uint64(increasedEstimation), nil
|
||||
}
|
||||
|
||||
func (s *TransferBridge) Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error) {
|
||||
|
|
|
@ -510,7 +510,8 @@ func (r *Router) getBalance(ctx context.Context, network *params.Network, token
|
|||
func (r *Router) suggestedRoutes(
|
||||
ctx context.Context,
|
||||
sendType SendType,
|
||||
account common.Address,
|
||||
addrFrom common.Address,
|
||||
addrTo common.Address,
|
||||
amountIn *big.Int,
|
||||
tokenID string,
|
||||
disabledFromChainIDs,
|
||||
|
@ -553,7 +554,7 @@ func (r *Router) suggestedRoutes(
|
|||
continue
|
||||
}
|
||||
|
||||
token := sendType.FindToken(r.s, account, network, tokenID)
|
||||
token := sendType.FindToken(r.s, addrFrom, network, tokenID)
|
||||
if token == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -572,7 +573,7 @@ func (r *Router) suggestedRoutes(
|
|||
// Default value is 1 as in case of erc721 as we built the token we are sure the account owns it
|
||||
balance := big.NewInt(1)
|
||||
if sendType != ERC721Transfer {
|
||||
balance, err = r.getBalance(ctx, network, token, account)
|
||||
balance, err = r.getBalance(ctx, network, token, addrFrom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -586,7 +587,7 @@ func (r *Router) suggestedRoutes(
|
|||
maxAmountIn = amount
|
||||
}
|
||||
|
||||
nativeBalance, err := r.getBalance(ctx, network, nativeToken, account)
|
||||
nativeBalance, err := r.getBalance(ctx, network, nativeToken, addrFrom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -640,12 +641,12 @@ func (r *Router) suggestedRoutes(
|
|||
}
|
||||
gasLimit := uint64(0)
|
||||
if sendType.isTransfer() {
|
||||
gasLimit, err = bridge.EstimateGas(network, dest, account, token, amountIn)
|
||||
gasLimit, err = bridge.EstimateGas(network, dest, addrFrom, addrTo, token, amountIn)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
gasLimit = sendType.EstimateGas(r.s, network, account, tokenID)
|
||||
gasLimit = sendType.EstimateGas(r.s, network, addrFrom, tokenID)
|
||||
}
|
||||
requiredNativeBalance := new(big.Int).Mul(gweiToWei(maxFees), big.NewInt(int64(gasLimit)))
|
||||
// Removed the required fees from maxAMount in case of native token tx
|
||||
|
@ -655,7 +656,7 @@ func (r *Router) suggestedRoutes(
|
|||
if nativeBalance.Cmp(requiredNativeBalance) <= 0 {
|
||||
continue
|
||||
}
|
||||
approvalRequired, approvalAmountRequired, approvalGasLimit, approvalContractAddress, err := r.requireApproval(ctx, sendType, bridge, account, network, token, amountIn)
|
||||
approvalRequired, approvalAmountRequired, approvalGasLimit, approvalContractAddress, err := r.requireApproval(ctx, sendType, bridge, addrFrom, network, token, amountIn)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/status-im/status-go/account"
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/params"
|
||||
"github.com/status-im/status-go/rpc"
|
||||
)
|
||||
|
||||
|
@ -80,6 +81,21 @@ func (t *Transactor) NextNonce(rpcClient *rpc.Client, chainID uint64, from types
|
|||
wrapper := newRPCWrapper(rpcClient, chainID)
|
||||
return t.nonce.Next(wrapper, from)
|
||||
}
|
||||
func (t *Transactor) EstimateGas(network *params.Network, from common.Address, to common.Address, value *big.Int, input []byte) (uint64, error) {
|
||||
rpcWrapper := newRPCWrapper(t.rpcWrapper.RPCClient, network.ChainID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), t.rpcCallTimeout)
|
||||
defer cancel()
|
||||
|
||||
msg := ethereum.CallMsg{
|
||||
From: from,
|
||||
To: &to,
|
||||
Value: value,
|
||||
Data: input,
|
||||
}
|
||||
|
||||
return rpcWrapper.EstimateGas(ctx, msg)
|
||||
}
|
||||
|
||||
// SendTransaction is an implementation of eth_sendTransaction. It queues the tx to the sign queue.
|
||||
func (t *Transactor) SendTransaction(sendArgs SendTxArgs, verifiedAccount *account.SelectedExtKey) (hash types.Hash, err error) {
|
||||
|
|
Loading…
Reference in New Issue