decred.org/dcrdex@v1.0.5/client/asset/eth/contractor_test.go (about)

     1  package eth
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math/big"
     7  	"testing"
     8  
     9  	"decred.org/dcrdex/client/asset"
    10  	"decred.org/dcrdex/dex/encode"
    11  	dexeth "decred.org/dcrdex/dex/networks/eth"
    12  	swapv0 "decred.org/dcrdex/dex/networks/eth/contracts/v0"
    13  	"github.com/ethereum/go-ethereum/accounts/abi/bind"
    14  	"github.com/ethereum/go-ethereum/common"
    15  	"github.com/ethereum/go-ethereum/core/types"
    16  )
    17  
    18  type tContractV0 struct {
    19  	lastInits   []swapv0.ETHSwapInitiation
    20  	initErr     error
    21  	lastRedeems []swapv0.ETHSwapRedemption
    22  	redeemErr   error
    23  	swap        swapv0.ETHSwapSwap
    24  	swapErr     error
    25  }
    26  
    27  func (c *tContractV0) Initiate(opts *bind.TransactOpts, initiations []swapv0.ETHSwapInitiation) (*types.Transaction, error) {
    28  	c.lastInits = initiations
    29  	return nil, c.initErr
    30  }
    31  
    32  func (c *tContractV0) Redeem(opts *bind.TransactOpts, redemptions []swapv0.ETHSwapRedemption) (*types.Transaction, error) {
    33  	c.lastRedeems = redemptions
    34  	return nil, c.redeemErr
    35  }
    36  
    37  func (c *tContractV0) Swap(opts *bind.CallOpts, secretHash [32]byte) (swapv0.ETHSwapSwap, error) {
    38  	return c.swap, c.swapErr
    39  }
    40  
    41  func (c *tContractV0) Refund(opts *bind.TransactOpts, secretHash [32]byte) (*types.Transaction, error) {
    42  	return nil, nil
    43  }
    44  
    45  func (c tContractV0) IsRefundable(opts *bind.CallOpts, secretHash [32]byte) (bool, error) {
    46  	return false, nil
    47  }
    48  
    49  func TestInitV0(t *testing.T) {
    50  	abiContract := &tContractV0{}
    51  	c := contractorV0{contractV0: abiContract, evmify: dexeth.GweiToWei}
    52  	addrStr := "0xB6De8BB5ed28E6bE6d671975cad20C03931bE981"
    53  	secretHashB := encode.RandomBytes(32)
    54  	const gweiVal = 123456
    55  	const lockTime = 100_000_000
    56  
    57  	contract := &asset.Contract{
    58  		SecretHash: secretHashB,
    59  		Address:    addrStr,
    60  		Value:      gweiVal,
    61  		LockTime:   lockTime,
    62  	}
    63  
    64  	contracts := []*asset.Contract{contract}
    65  
    66  	checkResult := func(tag string, wantErr bool) {
    67  		_, err := c.initiate(nil, contracts)
    68  		if (err != nil) != wantErr {
    69  			t.Fatal(tag)
    70  		}
    71  	}
    72  
    73  	checkResult("first success", false)
    74  
    75  	if len(abiContract.lastInits) != 1 {
    76  		t.Fatalf("wrong number of inits translated, %d", len(abiContract.lastInits))
    77  	}
    78  	init := abiContract.lastInits[0]
    79  	if init.RefundTimestamp.Uint64() != lockTime {
    80  		t.Fatalf("wrong RefundTimestamp. expected %d, got %d", lockTime, init.RefundTimestamp.Uint64())
    81  	}
    82  	if !bytes.Equal(init.SecretHash[:], secretHashB) {
    83  		t.Fatalf("wrong secret hash.")
    84  	}
    85  	if init.Participant != common.HexToAddress(addrStr) {
    86  		t.Fatalf("wrong address. wanted %s, got %s", common.HexToAddress(addrStr), init.Participant)
    87  	}
    88  	if dexeth.WeiToGwei(init.Value) != gweiVal {
    89  		t.Fatalf("wrong value. wanted %d, got %d", gweiVal, dexeth.WeiToGwei(init.Value))
    90  	}
    91  
    92  	// wrong secret hash size
    93  	contract.SecretHash = encode.RandomBytes(20)
    94  	checkResult("bad hash", true)
    95  	contract.SecretHash = encode.RandomBytes(32)
    96  
    97  	// dupe hash
    98  	contracts = []*asset.Contract{contract, contract}
    99  	checkResult("dupe hash", true)
   100  
   101  	// ok with two
   102  	contract2 := *contract
   103  	contract2.SecretHash = encode.RandomBytes(32)
   104  	contracts = []*asset.Contract{contract, &contract2}
   105  	checkResult("ok two", false)
   106  	contracts = []*asset.Contract{contract}
   107  
   108  	if len(abiContract.lastInits) != 2 {
   109  		t.Fatalf("two contracts weren't passed")
   110  	}
   111  
   112  	// bad address
   113  	contract.Address = "badaddress"
   114  	checkResult("bad address", true)
   115  	contract.Address = addrStr
   116  
   117  	// Initiate error
   118  	abiContract.initErr = fmt.Errorf("test error")
   119  	checkResult("contract error", true)
   120  	abiContract.initErr = nil
   121  
   122  	// Success again
   123  	checkResult("success again", false)
   124  }
   125  
   126  func TestRedeemV0(t *testing.T) {
   127  	abiContract := &tContractV0{}
   128  	c := contractorV0{contractV0: abiContract, evmify: dexeth.GweiToWei}
   129  
   130  	secretB := encode.RandomBytes(32)
   131  	secretHashB := encode.RandomBytes(32)
   132  
   133  	redemption := &asset.Redemption{
   134  		Secret: secretB,
   135  		Spends: &asset.AuditInfo{SecretHash: secretHashB},
   136  	}
   137  
   138  	redemptions := []*asset.Redemption{redemption}
   139  
   140  	checkResult := func(tag string, wantErr bool) {
   141  		_, err := c.redeem(nil, redemptions)
   142  		if (err != nil) != wantErr {
   143  			t.Fatal(tag, err)
   144  		}
   145  	}
   146  
   147  	checkResult("initial success", false)
   148  
   149  	if len(abiContract.lastRedeems) != 1 {
   150  		t.Fatalf("contract not passed")
   151  	}
   152  	redeem := abiContract.lastRedeems[0]
   153  	if !bytes.Equal(redeem.Secret[:], secretB) {
   154  		t.Fatalf("secret not translated")
   155  	}
   156  	if !bytes.Equal(redeem.SecretHash[:], secretHashB) {
   157  		t.Fatalf("secret hash not translated")
   158  	}
   159  
   160  	// bad secret hash length
   161  	redemption.Spends.SecretHash = encode.RandomBytes(20)
   162  	checkResult("bad secret hash length", true)
   163  	redemption.Spends.SecretHash = encode.RandomBytes(32)
   164  
   165  	// bad secret length
   166  	redemption.Secret = encode.RandomBytes(20)
   167  	checkResult("bad secret length", true)
   168  	redemption.Secret = encode.RandomBytes(32)
   169  
   170  	// Redeem error
   171  	abiContract.redeemErr = fmt.Errorf("test error")
   172  	checkResult("contract error", true)
   173  	abiContract.redeemErr = nil
   174  
   175  	// Error on dupe.
   176  	redemptions = []*asset.Redemption{redemption, redemption}
   177  	checkResult("dupe error", true)
   178  
   179  	// two OK
   180  	redemption2 := &asset.Redemption{
   181  		Secret: encode.RandomBytes(32),
   182  		Spends: &asset.AuditInfo{SecretHash: encode.RandomBytes(32)},
   183  	}
   184  	redemptions = []*asset.Redemption{redemption, redemption2}
   185  	checkResult("two ok", false)
   186  }
   187  
   188  func TestSwapV0(t *testing.T) {
   189  	abiContract := &tContractV0{}
   190  	c := contractorV0{
   191  		contractV0: abiContract,
   192  		evmify:     dexeth.GweiToWei,
   193  		atomize:    dexeth.WeiToGwei,
   194  	}
   195  
   196  	var secret [32]byte
   197  	const valGwei = 123_456
   198  	const blockNum = 654_321
   199  	const stamp = 789_654
   200  	var initiator, participant common.Address
   201  	copy(initiator[:], encode.RandomBytes(32))
   202  	copy(participant[:], encode.RandomBytes(32))
   203  	const state = 128
   204  
   205  	abiContract.swap = swapv0.ETHSwapSwap{
   206  		Secret:               secret,
   207  		Value:                dexeth.GweiToWei(valGwei),
   208  		InitBlockNumber:      big.NewInt(blockNum),
   209  		RefundBlockTimestamp: big.NewInt(stamp),
   210  		Initiator:            initiator,
   211  		Participant:          participant,
   212  		State:                state,
   213  	}
   214  
   215  	// error path
   216  	abiContract.swapErr = fmt.Errorf("test error")
   217  	_, err := c.swap(nil, [32]byte{})
   218  	if err == nil {
   219  		t.Fatalf("swap error not transmitted")
   220  	}
   221  	abiContract.swapErr = nil
   222  
   223  	swap, err := c.swap(nil, [32]byte{})
   224  	if err != nil {
   225  		t.Fatalf("swap error: %v", err)
   226  	}
   227  
   228  	if swap.Secret != secret {
   229  		t.Fatalf("wrong secret")
   230  	}
   231  	if dexeth.WeiToGwei(swap.Value) != valGwei {
   232  		t.Fatalf("wrong value")
   233  	}
   234  	if swap.BlockHeight != blockNum {
   235  		t.Fatalf("wrong block height")
   236  	}
   237  	if swap.LockTime.Unix() != stamp {
   238  		t.Fatalf("wrong lock time")
   239  	}
   240  	if swap.Initiator != initiator {
   241  		t.Fatalf("initiator not transmitted")
   242  	}
   243  	if swap.Participant != participant {
   244  		t.Fatalf("participant not transmitted")
   245  	}
   246  	if swap.State != state {
   247  		t.Fatalf("state not transmitted")
   248  	}
   249  }