Skip to content

Commit

Permalink
eth/client: Redeem
Browse files Browse the repository at this point in the history
  • Loading branch information
martonp committed Nov 17, 2021
1 parent bf0c33e commit c073f85
Show file tree
Hide file tree
Showing 6 changed files with 587 additions and 57 deletions.
112 changes: 97 additions & 15 deletions client/asset/eth/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ type ethFetcher interface {
unlock(ctx context.Context, pw string, acct *accounts.Account) error
signData(addr common.Address, data []byte) ([]byte, error)
suggestGasTipCap(ctx context.Context) (*big.Int, error)
suggestGasPrice(ctx context.Context) (*big.Int, error)
}

// Check that ExchangeWallet satisfies the asset.Wallet interface.
Expand Down Expand Up @@ -737,20 +738,9 @@ func (eth *ExchangeWallet) Swap(swaps *asset.Swaps) ([]asset.Receipt, asset.Coin
return fail(fmt.Errorf("Swap: coin inputs value %d < required %d", totalInputValue, totalUsedValue))
}

suggestedGasTipCap, err := eth.node.suggestGasTipCap(eth.ctx)
gasTipCap, err := eth.gasTipCapToUse()
if err != nil {
return fail(fmt.Errorf("Swap: failed to get suggested gas tip cap %w", err))
}

var gasTipCap *big.Int
suggestedGasTipCapGwei, err := srveth.ToGwei(suggestedGasTipCap)
if err != nil {
return fail(fmt.Errorf("Swap: failed to convert to gwei: %w", err))
}
if suggestedGasTipCapGwei > MinGasTipCap {
gasTipCap = suggestedGasTipCap
} else {
gasTipCap = big.NewInt(MinGasTipCap * srveth.GweiFactor)
return fail(fmt.Errorf("Swap: unable to determine gas tip cap to use: %w", err))
}

opts := bind.TransactOpts{
Expand Down Expand Up @@ -796,10 +786,102 @@ func (eth *ExchangeWallet) Swap(swaps *asset.Swaps) ([]asset.Receipt, asset.Coin
return receipts, change, maxPossibleFee, nil
}

// gasTipCapToUse return the maximum of the gas tip cap suggested by
// the eth client and MinGasTipCap.
func (eth *ExchangeWallet) gasTipCapToUse() (*big.Int, error) {
suggestedGasTipCap, err := eth.node.suggestGasTipCap(eth.ctx)
if err != nil {
return nil, err
}

minGasTipCapWei := srveth.ToWei(MinGasTipCap)

if suggestedGasTipCap.Cmp(minGasTipCapWei) > 0 {
return suggestedGasTipCap, nil
} else {
return minGasTipCapWei, nil
}
}

// Redeem sends the redemption transaction, which may contain more than one
// redemption.
func (*ExchangeWallet) Redeem(form *asset.RedeemForm) ([]dex.Bytes, asset.Coin, uint64, error) {
return nil, nil, 0, asset.ErrNotImplemented
func (eth *ExchangeWallet) Redeem(form *asset.RedeemForm) ([]dex.Bytes, asset.Coin, uint64, error) {
fail := func(err error) ([]dex.Bytes, asset.Coin, uint64, error) {
return nil, nil, 0, err
}

if len(form.Redemptions) == 0 {
return fail(errors.New("Redeem: must be called with at least 1 redemption"))
}

inputs := make([]dex.Bytes, 0, len(form.Redemptions))
redemptions := make([]dexeth.ETHSwapRedemption, 0, len(form.Redemptions))
var redeemedValue uint64
for _, redemption := range form.Redemptions {
coinID := redemption.Spends.Coin.ID()
inputs = append(inputs, coinID)

decodedID, err := srveth.DecodeCoinID(coinID)
if err != nil {
return fail(err)
}
swapCoinID, ok := decodedID.(*srveth.SwapCoinID)
if !ok {
return fail(
fmt.Errorf("Redeem: coin id in redemption should be swap coin id, but got %T",
swapCoinID))
}
swap, err := eth.node.swap(eth.ctx, eth.acct, swapCoinID.SecretHash)
if err != nil {
return fail(fmt.Errorf("Redeem: unable to retrieve swap: %w", err))
}
swapValue, err := srveth.ToGwei(swap.Value)
if err != nil {
return fail(fmt.Errorf("Redeem: unable to convert value to gwei: %w", err))
}
redeemedValue += swapValue

var secret [32]byte
var secretHash [32]byte
copy(secret[:], redemption.Secret)
copy(secretHash[:], redemption.Spends.SecretHash)
redemptions = append(redemptions,
dexeth.ETHSwapRedemption{
Secret: secret,
SecretHash: secretHash,
})
}

gasTipCap, err := eth.gasTipCapToUse()
if err != nil {
return fail(fmt.Errorf("Swap: unable to determine gas tip cap to use: %w", err))
}

// TODO: make sure the amount we locked for redemption is enough to cover the gas
// fees.
gasFeeCap := srveth.ToWei(form.FeeSuggestion)
suggestedFeeRate, err := eth.node.suggestGasPrice(eth.ctx)
if err != nil {
return fail(fmt.Errorf("Swap: unable to retrieve suggested gas price: %w", err))
}
if suggestedFeeRate.Cmp(gasFeeCap) > 0 {
gasFeeCap = suggestedFeeRate
}

opts := bind.TransactOpts{
From: eth.acct.Address,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
Context: eth.ctx,
}
_, err = eth.node.redeem(&opts, eth.networkID, redemptions)
if err != nil {
return fail(fmt.Errorf("Redeem: redeem error: %w", err))
}

outputCoin := eth.createAmountCoin(redeemedValue)
gasRequired := srveth.GasToRedeemSwaps(uint64(len(redemptions)))
return inputs, outputCoin, gasRequired * form.FeeSuggestion, nil
}

// SignMessage signs the message with the private key associated with the
Expand Down

0 comments on commit c073f85

Please sign in to comment.