Skip to content

Commit

Permalink
Support estimate with gas limit as max (#28)
Browse files Browse the repository at this point in the history
* main_O3V2_new_checkfee

* Add fee checking with max limit

* Reformat with indention

Co-authored-by: rain-zxn <[email protected]>
  • Loading branch information
devfans and rain-zxn committed Jun 2, 2022
1 parent 785bd89 commit 13126eb
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 5 deletions.
18 changes: 13 additions & 5 deletions chains/bridge/fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@

package bridge

import "github.com/polynetwork/bridge-common/tools"
import (
"github.com/polynetwork/bridge-common/tools"
)

type CheckFeeStatus int

const (
SKIP CheckFeeStatus = -2 // Skip since not our tx
NOT_PAID CheckFeeStatus = -1 // Not paid or paid too low
MISSING CheckFeeStatus = 0 // Tx not received yet
PAID CheckFeeStatus = 1 // Paid and enough pass
SKIP CheckFeeStatus = -2 // Skip since not our tx
NOT_PAID CheckFeeStatus = -1 // Not paid or paid too low
MISSING CheckFeeStatus = 0 // Tx not received yet
PAID CheckFeeStatus = 1 // Paid and enough pass
PAID_LIMIT CheckFeeStatus = 2 // Paid but need EstimateGas
)

type CheckFeeRequest struct {
Expand All @@ -34,6 +37,7 @@ type CheckFeeRequest struct {
PolyHash string
Paid float64
Min float64
PaidGas float64
Status CheckFeeStatus
}

Expand All @@ -49,6 +53,10 @@ func (r *CheckFeeRequest) Missing() bool {
return r == nil || r.Status == MISSING
}

func (r *CheckFeeRequest) PaidLimit() bool {
return r != nil && r.Status == PAID_LIMIT
}

func (c *Client) CheckFee(req map[string]*CheckFeeRequest) (err error) {
return tools.PostJsonFor(c.address+"/newcheckfee", req, &req)
}
Expand Down
82 changes: 82 additions & 0 deletions wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ type IWallet interface {
SendWithAccount(account accounts.Account, addr common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, gasPriceX *big.Float, data []byte) (hash string, err error)
EstimateWithAccount(account accounts.Account, addr common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, gasPriceX *big.Float, data []byte) (hash string, err error)
Accounts() []accounts.Account
Select() (accounts.Account, Provider, NonceProvider)
GetBalance(common.Address) (*big.Int, error)
EstimateGasWithAccount(account accounts.Account, addr common.Address, amount *big.Int, data []byte) (gasPrice *big.Int, gasLimit uint64, err error)
SendWithMaxLimit(account accounts.Account, addr common.Address, amount *big.Int, maxLimit *big.Int, gasPrice *big.Int, gasPriceX *big.Float, data []byte) (hash string, err error)
}

type Wallet struct {
Expand Down Expand Up @@ -258,3 +261,82 @@ func (w *Wallet) Select() (accounts.Account, Provider, NonceProvider) {
func (w *Wallet) Upgrade() *EthWallet {
return &EthWallet{*w}
}

func (w *Wallet) EstimateGasWithAccount(account accounts.Account, addr common.Address, amount *big.Int, data []byte) (gasPrice *big.Int, gasLimit uint64, err error) {
gasPrice, err = w.GasPrice()
if err != nil {
err = fmt.Errorf("Get gas price error %v", err)
return
}
msg := ethereum.CallMsg{From: account.Address, To: &addr, GasPrice: gasPrice, Value: amount, Data: data}
gasLimit, err = w.sdk.Node().EstimateGas(context.Background(), msg)
if err != nil {
err = fmt.Errorf("Estimate gas limit error %v, account %s", err, account.Address)
return
}
return
}


func (w *Wallet) SendWithMaxLimit(account accounts.Account, addr common.Address, amount *big.Int, maxLimit *big.Int, gasPrice *big.Int, gasPriceX *big.Float, data []byte) (hash string, err error) {
if maxLimit == nil || maxLimit.Sign() <= 0 {
err = fmt.Errorf("max limit is zero or missing")
return
}
if gasPrice == nil || gasPrice.Sign() <= 0 {
gasPrice, err = w.GasPrice()
if err != nil {
err = fmt.Errorf("Get gas price error %v", err)
return
}
if gasPriceX != nil {
gasPrice, _ = new(big.Float).Mul(new(big.Float).SetInt(gasPrice), gasPriceX).Int(nil)
}
}

provider, nonces := w.GetAccount(account)
nonce, err := nonces.Acquire()
if err != nil {
return
}

var gasLimit uint64
msg := ethereum.CallMsg{From: account.Address, To: &addr, GasPrice: gasPrice, Value: amount, Data: data}
gasLimit, err = w.sdk.Node().EstimateGas(context.Background(), msg)
if err != nil {
nonces.Update(false)
if strings.Contains(err.Error(), "has been executed") {
log.Info("Transaction already executed")
return "", nil
}

err = fmt.Errorf("Estimate gas limit error %v, account %s", err, account.Address)
return
}

limit := GetChainGasLimit(w.chainId, gasLimit)
if limit < gasLimit {
nonces.Update(false)
err = fmt.Errorf("Send tx estimated gas limit(%v) higher than chain max limit %v", gasLimit, limit)
return
}

if maxLimit.Cmp(new(big.Int).Mul(big.NewInt(int64(limit)), gasPrice)) == -1 {
nonces.Update(false)
err = fmt.Errorf("Send tx estimated gas (limit %v, price %s) higher than max limit %s", limit, gasPrice, maxLimit)
return
}

tx := types.NewTransaction(nonce, addr, amount, limit, gasPrice, data)
tx, err = provider.SignTx(account, tx, big.NewInt(int64(w.chainId)))
if err != nil {
nonces.Update(false)
err = fmt.Errorf("Sign tx error %v", err)
return
}
log.Info("Compose dst chain tx", "hash", tx.Hash(), "account", account.Address)
err = w.sdk.Node().SendTransaction(context.Background(), tx)
//TODO: Check err here before update nonces
nonces.Update(true)
return tx.Hash().String(), err
}

0 comments on commit 13126eb

Please sign in to comment.