forked from taikoxyz/taiko-mono
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtypes.go
180 lines (143 loc) · 4.65 KB
/
types.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package relayer
import (
"context"
"fmt"
"math/big"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/taikoxyz/taiko-mono/packages/relayer/contracts/bridge"
"github.com/taikoxyz/taiko-mono/packages/relayer/contracts/tokenvault"
)
var (
ZeroHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")
ZeroAddress = common.HexToAddress("0x0000000000000000000000000000000000000000")
)
// IsInSlice determines whether v is in slice s
func IsInSlice[T comparable](v T, s []T) bool {
for _, e := range s {
if v == e {
return true
}
}
return false
}
type confirmer interface {
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
BlockNumber(ctx context.Context) (uint64, error)
}
// WaitReceipt keeps waiting until the given transaction has an execution
// receipt to know whether it was reverted or not.
func WaitReceipt(ctx context.Context, confirmer confirmer, txHash common.Hash) (*types.Receipt, error) {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
log.Infof("waiting for transaction receipt for txHash %v", txHash.Hex())
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-ticker.C:
receipt, err := confirmer.TransactionReceipt(ctx, txHash)
if err != nil {
continue
}
if receipt.Status != types.ReceiptStatusSuccessful {
return nil, fmt.Errorf("transaction reverted, hash: %s", txHash)
}
log.Infof("transaction receipt found for txHash %v", txHash.Hex())
return receipt, nil
}
}
}
// WaitConfirmations won't return before N blocks confirmations have been seen
// on destination chain.
func WaitConfirmations(ctx context.Context, confirmer confirmer, confirmations uint64, txHash common.Hash) error {
log.Infof("txHash %v beginning waiting for confirmations", txHash.Hex())
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
receipt, err := confirmer.TransactionReceipt(ctx, txHash)
if err != nil {
if err == ethereum.NotFound {
continue
}
log.Errorf("txHash: %v encountered error getting receipt: %v", txHash.Hex(), err)
return err
}
latest, err := confirmer.BlockNumber(ctx)
if err != nil {
return err
}
want := receipt.BlockNumber.Uint64() + confirmations
log.Infof(
"txHash: %v waiting for %v confirmations which will happen in block number: %v, latestBlockNumber: %v",
txHash.Hex(),
confirmations,
want,
latest,
)
if latest < receipt.BlockNumber.Uint64()+confirmations {
continue
}
log.Infof("txHash %v received %v confirmations, done", txHash.Hex(), confirmations)
return nil
}
}
}
func DecodeMessageSentData(event *bridge.BridgeMessageSent) (EventType, *CanonicalToken, *big.Int, error) {
eventType := EventTypeSendETH
var canonicalToken CanonicalToken
var amount *big.Int
if event.Message.Data != nil && common.BytesToHash(event.Message.Data) != ZeroHash {
tokenVaultMD := bind.MetaData{
ABI: tokenvault.TokenVaultABI,
}
tokenVaultABI, err := tokenVaultMD.GetAbi()
if err != nil {
return eventType, nil, big.NewInt(0), errors.Wrap(err, "tokenVaultMD.GetAbi()")
}
method, err := tokenVaultABI.MethodById(event.Message.Data[:4])
if err != nil {
return eventType, nil, big.NewInt(0), errors.Wrap(err, "tokenVaultABI.MethodById")
}
inputsMap := make(map[string]interface{})
if err := method.Inputs.UnpackIntoMap(inputsMap, event.Message.Data[4:]); err != nil {
return eventType, nil, big.NewInt(0), errors.Wrap(err, "method.Inputs.UnpackIntoMap")
}
if method.Name == "receiveERC20" {
eventType = EventTypeSendERC20
canonicalToken = inputsMap["canonicalToken"].(struct {
// nolint
ChainId *big.Int `json:"chainId"`
Addr common.Address `json:"addr"`
Decimals uint8 `json:"decimals"`
Symbol string `json:"symbol"`
Name string `json:"name"`
})
amount = inputsMap["amount"].(*big.Int)
}
} else {
amount = event.Message.DepositValue
}
return eventType, &canonicalToken, amount, nil
}
type CanonicalToken struct {
// nolint
ChainId *big.Int `json:"chainId"`
Addr common.Address `json:"addr"`
Decimals uint8 `json:"decimals"`
Symbol string `json:"symbol"`
Name string `json:"name"`
}
type EthClient interface {
BlockNumber(ctx context.Context) (uint64, error)
ChainID(ctx context.Context) (*big.Int, error)
}