mirror of
https://github.com/AthanorLabs/atomic-swap.git
synced 2026-01-08 21:58:07 -05:00
fix: set GasLimit for relayed transactions (#425)
Co-authored-by: Dmitry Holodov <dimalinux@protonmail.com>
This commit is contained in:
@@ -60,7 +60,7 @@ func (h *Host) handleRelayStream(stream libp2pnetwork.Stream) {
|
||||
// (2) If the request is purportedly from a maker to a taker of a current
|
||||
// swap, then:
|
||||
// (a) The swap should exist in our swaps map
|
||||
// (b) The peerID who sent us the request much match the peerID with
|
||||
// (b) The peerID who sent us the request must match the peerID with
|
||||
// whom we are performing the swap.
|
||||
if req.OfferID == nil && !h.isRelayer {
|
||||
return
|
||||
@@ -120,7 +120,7 @@ func receiveRelayClaimResponse(stream libp2pnetwork.Stream) (*RelayClaimResponse
|
||||
// The timeout should be short enough, that the Maker can try multiple relayers
|
||||
// before T1 expires even if the receiving node accepts the relay request and
|
||||
// just sits on it without doing anything.
|
||||
const relayResponseTimeout = time.Second * 45
|
||||
const relayResponseTimeout = time.Minute
|
||||
|
||||
select {
|
||||
case msg := <-nextStreamMessage(stream, maxMessageSize):
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
@@ -15,9 +16,11 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
|
||||
"github.com/athanorlabs/atomic-swap/coins"
|
||||
"github.com/athanorlabs/atomic-swap/common"
|
||||
"github.com/athanorlabs/atomic-swap/common/types"
|
||||
"github.com/athanorlabs/atomic-swap/ethereum/block"
|
||||
"github.com/athanorlabs/atomic-swap/ethereum/extethclient"
|
||||
"github.com/athanorlabs/atomic-swap/net/message"
|
||||
"github.com/athanorlabs/atomic-swap/relayer"
|
||||
)
|
||||
@@ -39,12 +42,16 @@ func (s *swapState) claimFunds() (*ethtypes.Receipt, error) {
|
||||
log.Infof("balance before claim: %s %s", balance.AsStandardString(), balance.StandardSymbol())
|
||||
}
|
||||
|
||||
hasBalanceToClaim, err := checkForMinClaimBalance(s.ctx, s.ETHClient())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var receipt *ethtypes.Receipt
|
||||
|
||||
// call swap.Swap.Claim() w/ b.privkeys.sk, revealing XMRMaker's secret spend key
|
||||
if s.offerExtra.UseRelayer || weiBalance.Decimal().IsZero() {
|
||||
if s.offerExtra.UseRelayer || !hasBalanceToClaim {
|
||||
// relayer fee was set or we had insufficient funds to claim without a relayer
|
||||
// TODO: Sufficient funds check above should be more specific
|
||||
receipt, err = s.claimWithRelay()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to claim using relayers: %w", err)
|
||||
@@ -81,6 +88,40 @@ func (s *swapState) claimFunds() (*ethtypes.Receipt, error) {
|
||||
return receipt, nil
|
||||
}
|
||||
|
||||
// checkForMinClaimBalance check if we have enough balance to call claim.
|
||||
// return true if we do, false otherwise.
|
||||
func checkForMinClaimBalance(ctx context.Context, ec extethclient.EthClient) (bool, error) {
|
||||
// gas cost for ETH-claim is 42965
|
||||
// gas cost for ERC20-claim is 47138
|
||||
// add a bit of leeway to allow for sudden gas price spikes
|
||||
const claimGas = 50000
|
||||
|
||||
balance, err := ec.Balance(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if balance.Decimal().IsZero() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
gasPrice, err := ec.SuggestGasPrice(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
txCost := new(big.Int).Mul(gasPrice, big.NewInt(claimGas))
|
||||
if balance.BigInt().Cmp(txCost) < 0 {
|
||||
log.Infof("balance %s ETH is under the minimum %s ETH to call claim, using a relayer",
|
||||
balance.AsEtherString(),
|
||||
coins.FmtWeiAsETH(txCost),
|
||||
)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// relayClaimWithXMRTaker relays the claim to the swap's XMR taker, who should
|
||||
// process the claim even if they are not relaying claims for everyone.
|
||||
func (s *swapState) relayClaimWithXMRTaker(request *message.RelayClaimRequest) (*ethtypes.Receipt, error) {
|
||||
@@ -106,7 +147,6 @@ func (s *swapState) relayClaimWithXMRTaker(request *message.RelayClaimRequest) (
|
||||
}
|
||||
|
||||
log.Infof("relayer's claim via counterparty included and validated %s", common.ReceiptInfo(receipt))
|
||||
|
||||
return receipt, nil
|
||||
}
|
||||
|
||||
@@ -128,6 +168,7 @@ func (s *swapState) claimWithAdvertisedRelayers(request *message.RelayClaimReque
|
||||
log.Debugf("skipping DHT-advertised relayer that is our swap counterparty")
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("submitting claim to relayer with peer ID %s", relayerPeerID)
|
||||
resp, err := s.Backend.SubmitClaimToRelayer(relayerPeerID, request)
|
||||
if err != nil {
|
||||
|
||||
@@ -196,16 +196,9 @@ func (s *swapState) handleEvent(event Event) {
|
||||
err := s.handleNotifyETHLocked(e.message)
|
||||
if err != nil {
|
||||
e.errCh <- fmt.Errorf("failed to handle EventETHLocked: %w", err)
|
||||
if !s.fundsLocked {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = s.setNextExpectedEvent(EventContractReadyType)
|
||||
if err != nil {
|
||||
e.errCh <- fmt.Errorf("failed to set next expected event to EventContractReadyType: %w", err)
|
||||
return
|
||||
}
|
||||
// nextExpectedEvent was set in s.lockFunds()
|
||||
case *EventContractReady:
|
||||
log.Infof("EventContractReady")
|
||||
defer close(e.errCh)
|
||||
|
||||
@@ -77,8 +77,6 @@ type swapState struct {
|
||||
|
||||
// tracks the state of the swap
|
||||
nextExpectedEvent EventType
|
||||
// set to true once funds are locked
|
||||
fundsLocked bool
|
||||
|
||||
readyWatcher *watcher.EventFilter
|
||||
|
||||
@@ -654,8 +652,15 @@ func (s *swapState) lockFunds(amount *coins.PiconeroAmount) error {
|
||||
|
||||
log.Debug("total XMR balance: ", coins.FmtPiconeroAsXMR(balance.Balance))
|
||||
log.Info("unlocked XMR balance: ", coins.FmtPiconeroAsXMR(balance.UnlockedBalance))
|
||||
|
||||
log.Infof("Starting lock of %s XMR in address %s", amount.AsMoneroString(), swapDestAddr)
|
||||
|
||||
// set next expected event here, otherwise if we restart while `Transfer` is happening,
|
||||
// we won't notice that we already locked the XMR on restart.
|
||||
err = s.setNextExpectedEvent(EventContractReadyType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set next expected event to EventContractReadyType: %w", err)
|
||||
}
|
||||
|
||||
transfer, err := s.XMRClient().Transfer(s.ctx, swapDestAddr, 0, amount, monero.MinSpendConfirmations)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -663,6 +668,5 @@ func (s *swapState) lockFunds(amount *coins.PiconeroAmount) error {
|
||||
|
||||
log.Infof("Successfully locked XMR funds: txID=%s address=%s block=%d",
|
||||
transfer.TxID, swapDestAddr, transfer.Height)
|
||||
s.fundsLocked = true
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -117,5 +117,11 @@ func (s *swapState) claimMonero(skB *mcrypto.PrivateSpendKey) (*mcrypto.Address,
|
||||
|
||||
close(s.claimedCh)
|
||||
log.Infof("monero claimed and swept to original account %s", depositAddr)
|
||||
go func() {
|
||||
err = s.Exit()
|
||||
if err != nil {
|
||||
log.Warnf("failed to exit: %v", err)
|
||||
}
|
||||
}()
|
||||
return kpAB.PublicKeyPair().Address(s.Env()), nil
|
||||
}
|
||||
|
||||
@@ -78,6 +78,8 @@ func ValidateAndSendTransaction(
|
||||
return nil, err
|
||||
}
|
||||
txOpts.GasPrice = gasPrice
|
||||
txOpts.GasLimit = forwarderClaimGas
|
||||
log.Debugf("relaying tx with gas price %s and gas limit %d", gasPrice, txOpts.GasLimit)
|
||||
|
||||
err = simulateExecute(
|
||||
ctx,
|
||||
@@ -101,6 +103,7 @@ func ValidateAndSendTransaction(
|
||||
req.Signature,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("failed to call execute: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user