Skip to content

Commit

Permalink
eth: supplement eth swap receipt
Browse files Browse the repository at this point in the history
This supplements the swapRecipt String method with the contract address,
which in addition to the secret hash makes performing a manual refund
more straightforward.

This also omits the raw refund transaction logging in
(*Core).swapMatchGroup when the Receipt.SignedRefund provides no such
data, as is the case with ETH.
The swap Receipt's Stringer is still used here to log the secret hash
and contract address for ETH swapReceipts.
  • Loading branch information
chappjc committed Feb 3, 2022
1 parent 8e22b7f commit 0063ee6
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 20 deletions.
27 changes: 17 additions & 10 deletions client/asset/eth/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -631,9 +631,10 @@ type swapReceipt struct {
secretHash [dexeth.SecretHashSize]byte
// expiration and value can be determined with a blockchain
// lookup, but we cache these values to avoid this.
expiration time.Time
value uint64
ver uint32
expiration time.Time
value uint64
ver uint32
contractAddr string // specified by ver, here for naive consumers
}

// Expiration returns the time after which the contract can be
Expand All @@ -656,9 +657,14 @@ func (r *swapReceipt) Contract() dex.Bytes {
return dexeth.EncodeContractData(r.ver, r.secretHash)
}

// String returns a string representation of the swapReceipt.
// String returns a string representation of the swapReceipt. The secret hash
// and contract address should be included in this to facilitate a manual refund
// since the secret hash is identifies the swap in the contract (for v0).
// Although the user can pick this information from the transaction's "to"
// address and the calldata, this simplifies the process.
func (r *swapReceipt) String() string {
return fmt.Sprintf("{ tx hash: %x, secret hash: %x }", r.txHash, r.secretHash)
return fmt.Sprintf("{ tx hash: %x, contract address: %s, secret hash: %x }",
r.txHash, r.contractAddr, r.secretHash)
}

// SignedRefund returns an empty byte array. ETH does not support a pre-signed
Expand Down Expand Up @@ -710,11 +716,12 @@ func (eth *ExchangeWallet) Swap(swaps *asset.Swaps) ([]asset.Receipt, asset.Coin
copy(secretHash[:], swap.SecretHash)
receipts = append(receipts,
&swapReceipt{
expiration: encode.UnixTimeMilli(int64(swap.LockTime)),
value: swap.Value,
txHash: txHash,
secretHash: secretHash,
ver: swaps.AssetVersion,
expiration: encode.UnixTimeMilli(int64(swap.LockTime)),
value: swap.Value,
txHash: txHash,
secretHash: secretHash,
ver: swaps.AssetVersion,
contractAddr: dexeth.ContractAddresses[swaps.AssetVersion][eth.net].String(),
})
}

Expand Down
5 changes: 3 additions & 2 deletions client/asset/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,13 +362,14 @@ type Coins []Coin
type Receipt interface {
// Expiration is the time lock expiration.
Expiration() time.Time
// Coin is the contract's coin.
// Coin is the swap initiation transaction's Coin.
Coin() Coin
// Contract is the unique swap contract data. This may be a redeem script
// for UTXO assets, or other information that uniquely identifies the swap
// for account-based assets e.g. a contract version and secret hash for ETH.
Contract() dex.Bytes
// String provides a human-readable representation of the contract's Coin.
// String provides a human-readable representation of the swap that may
// provide supplementary data to locate the swap.
String() string
// SignedRefund is a signed refund script that can be used to return
// funds to the user in the case a contract expires.
Expand Down
26 changes: 18 additions & 8 deletions client/core/trade.go
Original file line number Diff line number Diff line change
Expand Up @@ -1631,20 +1631,30 @@ func (c *Core) swapMatchGroup(t *trackedTrade, matches []*matchTracker, errs *er

refundTxs := ""
for i, r := range receipts {
refundTxs = fmt.Sprintf("%s%q: %s", refundTxs, r.Coin(), r.SignedRefund())
rawRefund := r.SignedRefund()
if len(rawRefund) == 0 { // e.g. eth
continue // in case others are not empty for some reason
}
refundTxs = fmt.Sprintf("%s%q: %s", refundTxs, r.Coin(), rawRefund)
if i != len(receipts)-1 {
refundTxs = fmt.Sprintf("%s, ", refundTxs)
}
}

c.log.Infof("Broadcasted transaction with %d swap contracts for order %v. Assigned fee rate = %d. Receipts (%s): %v.",
// Log the swap receipts. It is important to print the receipts as a
// Stringer to provide important data, such as the secret hash and contract
// address with ETH since it allows manually refunding.
c.log.Infof("Broadcasted transaction with %d swap contracts for order %v. "+
"Assigned fee rate = %d. Receipts (%s): %v.",
len(receipts), t.ID(), swaps.FeeRate, t.wallets.fromAsset.Symbol, receipts)
c.log.Infof("The following are contract identifiers mapped to raw refund "+
"transactions that are only valid after the swap contract expires. "+
"These are fallback transactions that can be used to return funds "+
"to your wallet in the case dexc no longer functions. They SHOULD "+
"NOT be used if dexc is running without error. dexc will refund "+
"failed contracts automatically.\nRefund Txs: {%s}", refundTxs)
if refundTxs != "" {
c.log.Infof("The following are contract identifiers mapped to raw refund "+
"transactions that are only valid after the swap contract expires. "+
"These are fallback transactions that can be used to return funds "+
"to your wallet in the case dexc no longer functions. They should "+
"NOT be used if dexc is operable. dexc will refund failed "+
"contracts automatically.\nRefund Txs: {%s}", refundTxs)
}

// If this is the first swap (and even if not), the funding coins
// would have been spent and unlocked.
Expand Down

0 comments on commit 0063ee6

Please sign in to comment.