-
Notifications
You must be signed in to change notification settings - Fork 47
/
fund.go
155 lines (129 loc) · 4.13 KB
/
fund.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
package app
import (
"context"
"fmt"
"math/big"
"github.com/omni-network/omni/e2e/app/eoa"
"github.com/omni-network/omni/lib/anvil"
"github.com/omni-network/omni/lib/errors"
"github.com/omni-network/omni/lib/log"
"github.com/omni-network/omni/lib/netconf"
"github.com/omni-network/omni/lib/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
const saneMaxEther = 5 // Maximum amount to fund in ether. // TODO(corver): Increase this.
// noAnvilDev returns a list of accounts that are not dev anvil accounts.
func noAnvilDev(accounts []common.Address) []common.Address {
var nonDevAccounts []common.Address
for _, account := range accounts {
if !anvil.IsDevAccount(account) {
nonDevAccounts = append(nonDevAccounts, account)
}
}
return nonDevAccounts
}
// accountsToFund returns a list of accounts to fund on anvil chains, based on the network.
func accountsToFund(network netconf.ID) []common.Address {
switch network {
case netconf.Staging:
return eoa.MustAddresses(netconf.Staging, eoa.AllRoles()...)
case netconf.Devnet:
return eoa.MustAddresses(netconf.Devnet, eoa.AllRoles()...)
default:
return []common.Address{}
}
}
// fundAccounts funds the EOAs that need funding (just on anvil chains, for now).
func fundAccounts(ctx context.Context, def Definition) error {
accounts := accountsToFund(def.Testnet.Network)
eth100 := new(big.Int).Mul(big.NewInt(params.Ether), big.NewInt(100))
for _, chain := range def.Testnet.AnvilChains {
if err := anvil.FundAccounts(ctx, chain.ExternalRPC, eth100, noAnvilDev(accounts)...); err != nil {
return errors.Wrap(err, "fund anvil account")
}
}
return nil
}
// FundEOAAccounts funds the EOAs that need funding to their target balance.
func FundEOAAccounts(ctx context.Context, def Definition) error {
network := networkFromDef(def)
accounts, ok := eoa.AllAccounts(network.ID)
if !ok {
return errors.New("no accounts found", "network", network.ID)
}
for _, account := range accounts {
if account.Address == common.HexToAddress(eoa.ZeroXDead) {
log.Info(ctx, "Skipping 0xdead account", "role", account.Role)
continue
}
for _, chain := range network.EVMChains() {
thresholds, ok := eoa.GetFundThresholds(network.ID, account.Role)
if !ok {
log.Warn(ctx, "Skipping account without fund thresholds", nil, "role", account.Role)
continue
}
backend, err := def.Backends().Backend(chain.ID)
if err != nil {
return errors.Wrap(err, "backend")
}
balance, err := backend.BalanceAt(ctx, account.Address, nil)
if err != nil {
// skip if we have rpc errors
continue
}
if thresholds.MinBalance().Cmp(balance) < 0 {
log.Info(ctx,
"Not funding account, balance sufficient",
"chain", chain.Name,
"role", account.Role,
"address", account.Address,
"type", account.Type,
"balance", etherStr(balance),
"min_threshold", etherStr(thresholds.MinBalance()),
)
continue
}
saneMax := new(big.Int).Mul(big.NewInt(saneMaxEther), big.NewInt(params.Ether))
amount := new(big.Int).Sub(thresholds.TargetBalance(), balance)
if amount.Cmp(big.NewInt(0)) <= 0 {
return errors.New("unexpected negative amount")
} else if amount.Cmp(saneMax) > 0 {
log.Warn(ctx, "Funding amount exceeds sane max, skipping", nil,
"chain", chain.Name,
"role", account.Role,
"amount", etherStr(amount),
"max", etherStr(saneMax),
)
continue
}
tx, _, err := backend.Send(ctx, eoa.Funder(), txmgr.TxCandidate{
To: &account.Address,
GasLimit: 100_000,
Value: amount,
})
if err != nil {
return errors.Wrap(err, "send tx")
}
b, err := backend.BalanceAt(ctx, account.Address, nil)
if err != nil {
return errors.Wrap(err, "get balance")
}
log.Info(ctx, "Account funded",
"chain", chain.Name,
"role", account.Role,
"address", account.Address,
"type", account.Type,
"amount_funded", etherStr(amount),
"resulting_balance", etherStr(b),
"tx", tx.Hash().Hex(),
)
}
}
return nil
}
func etherStr(amount *big.Int) string {
b, _ := amount.Float64()
b /= params.Ether
return fmt.Sprintf("%.4f", b)
}