-
Notifications
You must be signed in to change notification settings - Fork 119
/
Copy pathhelpers.go
142 lines (111 loc) · 4.41 KB
/
helpers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package e2etests
import (
"math/big"
"strconv"
"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcutil"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
"github.com/zeta-chain/zetacore/e2e/runner"
"github.com/zeta-chain/zetacore/e2e/utils"
"github.com/zeta-chain/zetacore/pkg/chains"
crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types"
)
func withdrawBTCZRC20(r *runner.E2ERunner, to btcutil.Address, amount *big.Int) *btcjson.TxRawResult {
tx, err := r.BTCZRC20.Approve(
r.ZEVMAuth,
r.BTCZRC20Addr,
big.NewInt(amount.Int64()*2),
) // approve more to cover withdraw fee
require.NoError(r, err)
receipt := utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
utils.RequireTxSuccessful(r, receipt)
// mine blocks if testing on regnet
stop := r.MineBlocksIfLocalBitcoin()
defer stop()
// withdraw 'amount' of BTC from ZRC20 to BTC address
tx, err = r.BTCZRC20.Withdraw(r.ZEVMAuth, []byte(to.EncodeAddress()), amount)
require.NoError(r, err)
receipt = utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout)
utils.RequireTxSuccessful(r, receipt)
// mine 10 blocks to confirm the withdrawal tx
_, err = r.GenerateToAddressIfLocalBitcoin(10, to)
require.NoError(r, err)
// get cctx and check status
cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, receipt.TxHash.Hex(), r.CctxClient, r.Logger, r.CctxTimeout)
utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_OutboundMined)
// get bitcoin tx according to the outTxHash in cctx
outTxHash := cctx.GetCurrentOutboundParam().Hash
hash, err := chainhash.NewHashFromStr(outTxHash)
require.NoError(r, err)
rawTx, err := r.BtcRPCClient.GetRawTransactionVerbose(hash)
require.NoError(r, err)
r.Logger.Info("raw tx:")
r.Logger.Info(" TxIn: %d", len(rawTx.Vin))
for idx, txIn := range rawTx.Vin {
r.Logger.Info(" TxIn %d:", idx)
r.Logger.Info(" TxID:Vout: %s:%d", txIn.Txid, txIn.Vout)
r.Logger.Info(" ScriptSig: %s", txIn.ScriptSig.Hex)
}
r.Logger.Info(" TxOut: %d", len(rawTx.Vout))
for _, txOut := range rawTx.Vout {
r.Logger.Info(" TxOut %d:", txOut.N)
r.Logger.Info(" Value: %.8f", txOut.Value)
r.Logger.Info(" ScriptPubKey: %s", txOut.ScriptPubKey.Hex)
}
return rawTx
}
// verifyTransferAmountFromCCTX verifies the transfer amount from the CCTX on EVM
func verifyTransferAmountFromCCTX(r *runner.E2ERunner, cctx *crosschaintypes.CrossChainTx, amount int64) {
r.Logger.Info("outTx hash %s", cctx.GetCurrentOutboundParam().Hash)
receipt, err := r.EVMClient.TransactionReceipt(
r.Ctx,
ethcommon.HexToHash(cctx.GetCurrentOutboundParam().Hash),
)
require.NoError(r, err)
r.Logger.Info("Receipt txhash %s status %d", receipt.TxHash, receipt.Status)
for _, log := range receipt.Logs {
event, err := r.ERC20.ParseTransfer(*log)
if err != nil {
continue
}
r.Logger.Info(" logs: from %s, to %s, value %d", event.From.Hex(), event.To.Hex(), event.Value)
require.Equal(r, amount, event.Value.Int64(), "value is not correct")
}
}
// Parse helpers ==========================================>
func parseFloat(t require.TestingT, s string) float64 {
f, err := strconv.ParseFloat(s, 64)
require.NoError(t, err, "unable to parse float %q", s)
return f
}
func parseInt(t require.TestingT, s string) int {
v, err := strconv.Atoi(s)
require.NoError(t, err, "unable to parse int from %q", s)
return v
}
func parseBigInt(t require.TestingT, s string) *big.Int {
v, ok := big.NewInt(0).SetString(s, 10)
require.True(t, ok, "unable to parse big.Int from %q", s)
return v
}
// bigIntFromFloat64 takes float64 (e.g. 0.001) that represents btc amount
// and converts it to big.Int for downstream usage.
func btcAmountFromFloat64(t require.TestingT, amount float64) *big.Int {
satoshi, err := btcutil.NewAmount(amount)
require.NoError(t, err)
return big.NewInt(int64(satoshi))
}
func parseBitcoinWithdrawArgs(r *runner.E2ERunner, args []string, defaultReceiver string) (btcutil.Address, *big.Int) {
require.NotEmpty(r, args, "args list is empty")
receiverRaw := defaultReceiver
if args[0] != "" {
receiverRaw = args[0]
}
receiver, err := chains.DecodeBtcAddress(receiverRaw, r.GetBitcoinChainID())
require.NoError(r, err, "unable to decode btc address")
withdrawalAmount := parseFloat(r, args[1])
amount := btcAmountFromFloat64(r, withdrawalAmount)
return receiver, amount
}