mirror of
https://github.com/AthanorLabs/atomic-swap.git
synced 2026-01-09 22:28:04 -05:00
611 lines
18 KiB
Go
611 lines
18 KiB
Go
// Copyright 2023 The AthanorLabs/atomic-swap Authors
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
package contracts
|
|
|
|
import (
|
|
"context"
|
|
"crypto/ecdsa"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"math/big"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
ethcommon "github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/athanorlabs/atomic-swap/common"
|
|
"github.com/athanorlabs/atomic-swap/common/types"
|
|
"github.com/athanorlabs/atomic-swap/crypto/secp256k1"
|
|
"github.com/athanorlabs/atomic-swap/dleq"
|
|
"github.com/athanorlabs/atomic-swap/ethereum/block"
|
|
"github.com/athanorlabs/atomic-swap/tests"
|
|
)
|
|
|
|
var (
|
|
defaultTimeoutDuration = big.NewInt(60) // 60 seconds
|
|
ethAssetAddress = ethcommon.Address(types.EthAssetETH)
|
|
defaultSwapValue = big.NewInt(100)
|
|
)
|
|
|
|
func setupXMRTakerAuth(t *testing.T) (*bind.TransactOpts, *ethclient.Client, *ecdsa.PrivateKey) {
|
|
conn, _ := tests.NewEthClient(t)
|
|
pkA := tests.GetTakerTestKey(t)
|
|
chainID, err := conn.ChainID(context.Background())
|
|
require.NoError(t, err)
|
|
auth, err := bind.NewKeyedTransactorWithChainID(pkA, chainID)
|
|
require.NoError(t, err)
|
|
return auth, conn, pkA
|
|
}
|
|
|
|
func approveERC20(t *testing.T,
|
|
auth *bind.TransactOpts,
|
|
conn *ethclient.Client,
|
|
erc20Contract *TestERC20,
|
|
swapCreatorAddress ethcommon.Address,
|
|
value *big.Int,
|
|
) {
|
|
require.NotNil(t, erc20Contract)
|
|
tx, err := erc20Contract.Approve(auth, swapCreatorAddress, value)
|
|
require.NoError(t, err)
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call Approve: %d", receipt.GasUsed)
|
|
}
|
|
|
|
func testNewSwap(t *testing.T, asset ethcommon.Address, erc20Contract *TestERC20) {
|
|
auth, conn, _ := setupXMRTakerAuth(t)
|
|
address, tx, contract, err := DeploySwapCreator(auth, conn, ethcommon.Address{})
|
|
require.NoError(t, err)
|
|
require.NotEqual(t, ethcommon.Address{}, address)
|
|
require.NotNil(t, tx)
|
|
require.NotNil(t, contract)
|
|
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to deploy SwapCreator.sol: %d", receipt.GasUsed)
|
|
|
|
owner := auth.From
|
|
claimer := common.EthereumPrivateKeyToAddress(tests.GetMakerTestKey(t))
|
|
|
|
var pubKeyClaim, pubKeyRefund [32]byte
|
|
_, err = rand.Read(pubKeyClaim[:])
|
|
require.NoError(t, err)
|
|
_, err = rand.Read(pubKeyRefund[:])
|
|
require.NoError(t, err)
|
|
|
|
nonce, err := rand.Prime(rand.Reader, 256)
|
|
require.NoError(t, err)
|
|
|
|
value := defaultSwapValue
|
|
isEthAsset := asset == ethAssetAddress
|
|
|
|
if isEthAsset {
|
|
auth.Value = value
|
|
} else {
|
|
approveERC20(t, auth, conn, erc20Contract, address, value)
|
|
}
|
|
|
|
tx, err = contract.NewSwap(
|
|
auth,
|
|
pubKeyClaim,
|
|
pubKeyRefund,
|
|
claimer,
|
|
defaultTimeoutDuration,
|
|
defaultTimeoutDuration,
|
|
asset,
|
|
value,
|
|
nonce,
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call new_swap: %d", receipt.GasUsed)
|
|
|
|
newSwapLogIndex := 0
|
|
if !isEthAsset {
|
|
newSwapLogIndex = 2
|
|
}
|
|
require.Equal(t, newSwapLogIndex+1, len(receipt.Logs))
|
|
|
|
swapID, err := GetIDFromLog(receipt.Logs[newSwapLogIndex])
|
|
require.NoError(t, err)
|
|
|
|
t0, t1, err := GetTimeoutsFromLog(receipt.Logs[newSwapLogIndex])
|
|
require.NoError(t, err)
|
|
|
|
// validate that off-chain swapID calculation matches the on-chain value
|
|
swap := SwapCreatorSwap{
|
|
Owner: owner,
|
|
Claimer: claimer,
|
|
PubKeyClaim: pubKeyClaim,
|
|
PubKeyRefund: pubKeyRefund,
|
|
Timeout0: t0,
|
|
Timeout1: t1,
|
|
Asset: asset,
|
|
Value: value,
|
|
Nonce: nonce,
|
|
}
|
|
|
|
// validate our off-net calculation of the SwapID
|
|
require.Equal(t, types.Hash(swapID).Hex(), swap.SwapID().Hex())
|
|
}
|
|
|
|
func TestSwapCreator_NewSwap(t *testing.T) {
|
|
testNewSwap(t, ethAssetAddress, nil)
|
|
}
|
|
|
|
func TestSwapCreator_Claim_vec(t *testing.T) {
|
|
secret, err := hex.DecodeString("D30519BCAE8D180DBFCC94FE0B8383DC310185B0BE97B4365083EBCECCD75759")
|
|
require.NoError(t, err)
|
|
pubX, err := hex.DecodeString("3AF1E1EFA4D1E1AD5CB9E3967E98E901DAFCD37C44CF0BFB6C216997F5EE51DF")
|
|
require.NoError(t, err)
|
|
pubY, err := hex.DecodeString("E4ACAC3E6F139E0C7DB2BD736824F51392BDA176965A1C59EB9C3C5FF9E85D7A")
|
|
require.NoError(t, err)
|
|
|
|
var s, x, y [32]byte
|
|
copy(s[:], secret)
|
|
copy(x[:], pubX)
|
|
copy(y[:], pubY)
|
|
|
|
pk := secp256k1.NewPublicKey(x, y)
|
|
cmt := pk.Keccak256()
|
|
|
|
// deploy swap contract with claim key hash
|
|
auth, conn, pkA := setupXMRTakerAuth(t)
|
|
pub := pkA.Public().(*ecdsa.PublicKey)
|
|
addr := crypto.PubkeyToAddress(*pub)
|
|
|
|
_, tx, contract, err := DeploySwapCreator(auth, conn, ethcommon.Address{})
|
|
require.NoError(t, err)
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to deploy SwapCreator.sol: %d", receipt.GasUsed)
|
|
|
|
nonce := big.NewInt(0)
|
|
auth.Value = defaultSwapValue
|
|
tx, err = contract.NewSwap(auth, cmt, [32]byte{}, addr, defaultTimeoutDuration,
|
|
defaultTimeoutDuration, ethcommon.Address(types.EthAssetETH), defaultSwapValue, nonce)
|
|
require.NoError(t, err)
|
|
auth.Value = nil
|
|
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call new_swap: %d", receipt.GasUsed)
|
|
|
|
require.Equal(t, 1, len(receipt.Logs))
|
|
id, err := GetIDFromLog(receipt.Logs[0])
|
|
require.NoError(t, err)
|
|
|
|
t0, t1, err := GetTimeoutsFromLog(receipt.Logs[0])
|
|
require.NoError(t, err)
|
|
|
|
swap := SwapCreatorSwap{
|
|
Owner: addr,
|
|
Claimer: addr,
|
|
PubKeyClaim: cmt,
|
|
PubKeyRefund: [32]byte{},
|
|
Timeout0: t0,
|
|
Timeout1: t1,
|
|
Asset: ethcommon.Address(types.EthAssetETH),
|
|
Value: defaultSwapValue,
|
|
Nonce: nonce,
|
|
}
|
|
|
|
// set contract to Ready
|
|
tx, err = contract.SetReady(auth, swap)
|
|
require.NoError(t, err)
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call set_ready: %d", receipt.GasUsed)
|
|
|
|
// now let's try to claim
|
|
tx, err = contract.Claim(auth, swap, s)
|
|
require.NoError(t, err)
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call claim: %d", receipt.GasUsed)
|
|
|
|
stage, err := contract.Swaps(nil, id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, StageCompleted, stage)
|
|
}
|
|
|
|
func testClaim(t *testing.T, asset ethcommon.Address, newLogIndex int, value *big.Int, erc20Contract *TestERC20) {
|
|
// generate claim secret and public key
|
|
dleq := &dleq.DefaultDLEq{}
|
|
proof, err := dleq.Prove()
|
|
require.NoError(t, err)
|
|
res, err := dleq.Verify(proof)
|
|
require.NoError(t, err)
|
|
|
|
// hash public key
|
|
cmt := res.Secp256k1PublicKey().Keccak256()
|
|
|
|
// deploy swap contract with claim key hash
|
|
authOrig, conn, pkA := setupXMRTakerAuth(t)
|
|
pub := pkA.Public().(*ecdsa.PublicKey)
|
|
addr := crypto.PubkeyToAddress(*pub)
|
|
|
|
// TODO: Rewrite this code to avoid the awkward use of txOpts. Code was using
|
|
// same TxOpts for multiple transactions and we needed a quick fix to get
|
|
// CI working.
|
|
txOpts := *authOrig
|
|
swapCreatorAddr, tx, contract, err := DeploySwapCreator(&txOpts, conn, ethcommon.Address{})
|
|
require.NoError(t, err)
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to deploy SwapCreator.sol: %d", receipt.GasUsed)
|
|
|
|
if asset != ethAssetAddress {
|
|
approveERC20(t, authOrig, conn, erc20Contract, swapCreatorAddr, value)
|
|
}
|
|
|
|
nonce := big.NewInt(0)
|
|
txOpts = *authOrig
|
|
if asset == ethAssetAddress {
|
|
txOpts.Value = value
|
|
}
|
|
|
|
tx, err = contract.NewSwap(&txOpts, cmt, [32]byte{}, addr,
|
|
defaultTimeoutDuration, defaultTimeoutDuration, asset, value, nonce)
|
|
require.NoError(t, err)
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call new_swap: %d", receipt.GasUsed)
|
|
|
|
require.Equal(t, newLogIndex+1, len(receipt.Logs))
|
|
id, err := GetIDFromLog(receipt.Logs[newLogIndex])
|
|
require.NoError(t, err)
|
|
|
|
t0, t1, err := GetTimeoutsFromLog(receipt.Logs[newLogIndex])
|
|
require.NoError(t, err)
|
|
|
|
swap := SwapCreatorSwap{
|
|
Owner: addr,
|
|
Claimer: addr,
|
|
PubKeyClaim: cmt,
|
|
PubKeyRefund: [32]byte{},
|
|
Timeout0: t0,
|
|
Timeout1: t1,
|
|
Asset: asset,
|
|
Value: value,
|
|
Nonce: nonce,
|
|
}
|
|
|
|
// ensure we can't claim before setting contract to Ready
|
|
txOpts = *authOrig
|
|
_, err = contract.Claim(&txOpts, swap, proof.Secret())
|
|
require.ErrorContains(t, err, "VM Exception while processing transaction: revert")
|
|
|
|
// set contract to Ready
|
|
txOpts = *authOrig
|
|
tx, err = contract.SetReady(&txOpts, swap)
|
|
require.NoError(t, err)
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
t.Logf("gas cost to call SetReady: %d", receipt.GasUsed)
|
|
require.NoError(t, err)
|
|
|
|
// now let's try to claim
|
|
txOpts = *authOrig
|
|
tx, err = contract.Claim(&txOpts, swap, proof.Secret())
|
|
require.NoError(t, err)
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call Claim: %d", receipt.GasUsed)
|
|
|
|
stage, err := contract.Swaps(nil, id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, StageCompleted, stage)
|
|
}
|
|
|
|
func TestSwapCreator_Claim_random(t *testing.T) {
|
|
testClaim(t, ethAssetAddress, 0, defaultSwapValue, nil)
|
|
}
|
|
|
|
func testRefundBeforeT0(t *testing.T, asset ethcommon.Address, erc20Contract *TestERC20, newLogIndex int) {
|
|
// generate refund secret and public key
|
|
dleq := &dleq.DefaultDLEq{}
|
|
proof, err := dleq.Prove()
|
|
require.NoError(t, err)
|
|
res, err := dleq.Verify(proof)
|
|
require.NoError(t, err)
|
|
|
|
// hash public key
|
|
cmt := res.Secp256k1PublicKey().Keccak256()
|
|
|
|
// deploy swap contract with refund key hash
|
|
auth, conn, pkA := setupXMRTakerAuth(t)
|
|
pub := pkA.Public().(*ecdsa.PublicKey)
|
|
addr := crypto.PubkeyToAddress(*pub)
|
|
|
|
address, tx, contract, err := DeploySwapCreator(auth, conn, ethcommon.Address{})
|
|
require.NoError(t, err)
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to deploy SwapCreator.sol: %d", receipt.GasUsed)
|
|
|
|
if asset != ethAssetAddress {
|
|
approveERC20(t, auth, conn, erc20Contract, address, defaultSwapValue)
|
|
}
|
|
|
|
nonce := big.NewInt(0)
|
|
auth.Value = defaultSwapValue
|
|
tx, err = contract.NewSwap(auth, [32]byte{}, cmt, addr, defaultTimeoutDuration, defaultTimeoutDuration,
|
|
asset, defaultSwapValue, nonce)
|
|
require.NoError(t, err)
|
|
auth.Value = nil
|
|
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call new_swap: %d", receipt.GasUsed)
|
|
|
|
require.Equal(t, newLogIndex+1, len(receipt.Logs))
|
|
id, err := GetIDFromLog(receipt.Logs[newLogIndex])
|
|
require.NoError(t, err)
|
|
|
|
t0, t1, err := GetTimeoutsFromLog(receipt.Logs[newLogIndex])
|
|
require.NoError(t, err)
|
|
|
|
swap := SwapCreatorSwap{
|
|
Owner: addr,
|
|
Claimer: addr,
|
|
PubKeyClaim: [32]byte{},
|
|
PubKeyRefund: cmt,
|
|
Timeout0: t0,
|
|
Timeout1: t1,
|
|
Asset: asset,
|
|
Value: defaultSwapValue,
|
|
Nonce: nonce,
|
|
}
|
|
|
|
// now let's try to refund
|
|
tx, err = contract.Refund(auth, swap, proof.Secret())
|
|
require.NoError(t, err)
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call Refund: %d", receipt.GasUsed)
|
|
|
|
stage, err := contract.Swaps(nil, id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, StageCompleted, stage)
|
|
}
|
|
|
|
func TestSwapCreator_Refund_beforeT0(t *testing.T) {
|
|
testRefundBeforeT0(t, ethAssetAddress, nil, 0)
|
|
}
|
|
|
|
func testRefundAfterT1(t *testing.T, asset ethcommon.Address, erc20Contract *TestERC20, newLogIndex int) {
|
|
// generate refund secret and public key
|
|
dleq := &dleq.DefaultDLEq{}
|
|
proof, err := dleq.Prove()
|
|
require.NoError(t, err)
|
|
res, err := dleq.Verify(proof)
|
|
require.NoError(t, err)
|
|
|
|
// hash public key
|
|
cmt := res.Secp256k1PublicKey().Keccak256()
|
|
|
|
// deploy swap contract with refund key hash
|
|
auth, conn, pkA := setupXMRTakerAuth(t)
|
|
pub := pkA.Public().(*ecdsa.PublicKey)
|
|
addr := crypto.PubkeyToAddress(*pub)
|
|
|
|
address, tx, contract, err := DeploySwapCreator(auth, conn, ethcommon.Address{})
|
|
require.NoError(t, err)
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to deploy SwapCreator.sol: %d", receipt.GasUsed)
|
|
|
|
if asset != ethAssetAddress {
|
|
approveERC20(t, auth, conn, erc20Contract, address, defaultSwapValue)
|
|
}
|
|
|
|
nonce := big.NewInt(0)
|
|
timeout := big.NewInt(3)
|
|
auth.Value = defaultSwapValue
|
|
tx, err = contract.NewSwap(auth, [32]byte{}, cmt, addr, timeout, timeout,
|
|
asset, defaultSwapValue, nonce)
|
|
require.NoError(t, err)
|
|
auth.Value = nil
|
|
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call new_swap: %d", receipt.GasUsed)
|
|
|
|
require.Equal(t, newLogIndex+1, len(receipt.Logs))
|
|
id, err := GetIDFromLog(receipt.Logs[newLogIndex])
|
|
require.NoError(t, err)
|
|
|
|
t0, t1, err := GetTimeoutsFromLog(receipt.Logs[newLogIndex])
|
|
require.NoError(t, err)
|
|
|
|
// ensure we can't refund between T0 and T1
|
|
<-time.After(time.Until(time.Unix(t0.Int64()+1, 0)))
|
|
swap := SwapCreatorSwap{
|
|
Owner: addr,
|
|
Claimer: addr,
|
|
PubKeyClaim: [32]byte{},
|
|
PubKeyRefund: cmt,
|
|
Timeout0: t0,
|
|
Timeout1: t1,
|
|
Asset: asset,
|
|
Value: defaultSwapValue,
|
|
Nonce: nonce,
|
|
}
|
|
|
|
secret := proof.Secret()
|
|
tx, err = contract.Refund(auth, swap, secret)
|
|
require.NoError(t, err)
|
|
_, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.ErrorContains(t, err, "VM Exception while processing transaction: revert")
|
|
|
|
<-time.After(time.Until(time.Unix(t1.Int64()+1, 0)))
|
|
|
|
// now let's try to refund
|
|
tx, err = contract.Refund(auth, swap, secret)
|
|
require.NoError(t, err)
|
|
receipt, err = block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call Refund: %d", receipt.GasUsed)
|
|
|
|
callOpts := &bind.CallOpts{
|
|
From: crypto.PubkeyToAddress(*pub),
|
|
Context: context.Background(),
|
|
}
|
|
|
|
stage, err := contract.Swaps(callOpts, id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, StageCompleted, stage)
|
|
}
|
|
|
|
func TestSwapCreator_Refund_afterT1(t *testing.T) {
|
|
testRefundAfterT1(t, ethAssetAddress, nil, 0)
|
|
}
|
|
|
|
func TestSwapCreator_MultipleSwaps(t *testing.T) {
|
|
// test case where contract has multiple swaps happening at once
|
|
conn, chainID := tests.NewEthClient(t)
|
|
|
|
pkContractCreator := tests.GetTestKeyByIndex(t, 0)
|
|
auth, err := bind.NewKeyedTransactorWithChainID(pkContractCreator, chainID)
|
|
require.NoError(t, err)
|
|
|
|
_, tx, contract, err := DeploySwapCreator(auth, conn, ethcommon.Address{})
|
|
require.NoError(t, err)
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to deploy SwapCreator.sol: %d", receipt.GasUsed)
|
|
|
|
const numSwaps = 16
|
|
type swapCase struct {
|
|
index int // index in the swap array
|
|
walletKey *ecdsa.PrivateKey
|
|
id [32]byte
|
|
secret [32]byte
|
|
swap SwapCreatorSwap
|
|
}
|
|
|
|
getAuth := func(sc *swapCase) *bind.TransactOpts {
|
|
auth, err := bind.NewKeyedTransactorWithChainID(sc.walletKey, chainID)
|
|
require.NoError(t, err)
|
|
return auth
|
|
}
|
|
|
|
swapCases := [numSwaps]swapCase{}
|
|
|
|
// setup all swap instances
|
|
for i := 0; i < numSwaps; i++ {
|
|
sc := &swapCases[i]
|
|
sc.index = i
|
|
|
|
// generate claim secret and public key
|
|
dleq := &dleq.DefaultDLEq{}
|
|
proof, err := dleq.Prove()
|
|
require.NoError(t, err)
|
|
res, err := dleq.Verify(proof)
|
|
require.NoError(t, err)
|
|
|
|
sc.secret = proof.Secret()
|
|
sc.walletKey = tests.GetTestKeyByIndex(t, i)
|
|
addrSwap := crypto.PubkeyToAddress(*sc.walletKey.Public().(*ecdsa.PublicKey))
|
|
|
|
sc.swap = SwapCreatorSwap{
|
|
Owner: addrSwap,
|
|
Claimer: addrSwap,
|
|
PubKeyClaim: res.Secp256k1PublicKey().Keccak256(),
|
|
PubKeyRefund: [32]byte{}, // no one calls refund in this test
|
|
Timeout0: nil, // timeouts initialised when swap is created
|
|
Timeout1: nil,
|
|
Asset: ethcommon.Address(types.EthAssetETH),
|
|
Value: defaultSwapValue,
|
|
Nonce: big.NewInt(int64(i)),
|
|
}
|
|
}
|
|
|
|
// We create all transactions in parallel, so the transactions of each swap stage can get bundled up
|
|
// into one or two blocks and greatly speed up the test.
|
|
var wg sync.WaitGroup
|
|
|
|
// create swap instances
|
|
wg.Add(numSwaps)
|
|
for i := 0; i < numSwaps; i++ {
|
|
go func(sc *swapCase) {
|
|
defer wg.Done()
|
|
auth := getAuth(sc)
|
|
auth.Value = sc.swap.Value
|
|
tx, err := contract.NewSwap(
|
|
auth,
|
|
sc.swap.PubKeyClaim,
|
|
sc.swap.PubKeyRefund,
|
|
sc.swap.Claimer,
|
|
defaultTimeoutDuration,
|
|
defaultTimeoutDuration,
|
|
ethcommon.Address(types.EthAssetETH),
|
|
sc.swap.Value,
|
|
sc.swap.Nonce,
|
|
)
|
|
require.NoError(t, err)
|
|
auth.Value = nil
|
|
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call new_swap[%d]: %d", sc.index, receipt.GasUsed)
|
|
|
|
require.Equal(t, 1, len(receipt.Logs))
|
|
sc.id, err = GetIDFromLog(receipt.Logs[0])
|
|
require.NoError(t, err)
|
|
|
|
sc.swap.Timeout0, sc.swap.Timeout1, err = GetTimeoutsFromLog(receipt.Logs[0])
|
|
require.NoError(t, err)
|
|
}(&swapCases[i])
|
|
}
|
|
wg.Wait() // all swaps created
|
|
|
|
// set all swaps to Ready
|
|
wg.Add(numSwaps)
|
|
for i := 0; i < numSwaps; i++ {
|
|
go func(sc *swapCase) {
|
|
defer wg.Done()
|
|
tx, err := contract.SetReady(getAuth(sc), sc.swap)
|
|
require.NoError(t, err)
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call SetReady[%d]: %d", sc.index, receipt.GasUsed)
|
|
}(&swapCases[i])
|
|
}
|
|
wg.Wait() // set_ready called on all swaps
|
|
|
|
// call claim on all the swaps
|
|
wg.Add(numSwaps)
|
|
for i := 0; i < numSwaps; i++ {
|
|
go func(sc *swapCase) {
|
|
defer wg.Done()
|
|
tx, err := contract.Claim(getAuth(sc), sc.swap, sc.secret)
|
|
require.NoError(t, err)
|
|
receipt, err := block.WaitForReceipt(context.Background(), conn, tx.Hash())
|
|
require.NoError(t, err)
|
|
t.Logf("gas cost to call Claim[%d]: %d", sc.index, receipt.GasUsed)
|
|
}(&swapCases[i])
|
|
}
|
|
wg.Wait() // claim called on all swaps
|
|
|
|
// ensure all swaps are completed
|
|
wg.Add(numSwaps)
|
|
for i := 0; i < numSwaps; i++ {
|
|
go func(sc *swapCase) {
|
|
defer wg.Done()
|
|
stage, err := contract.Swaps(nil, sc.id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, StageToString(StageCompleted), StageToString(stage))
|
|
}(&swapCases[i])
|
|
}
|
|
wg.Wait() // status of all swaps checked
|
|
}
|