-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy patherc20.go
115 lines (93 loc) · 3.54 KB
/
erc20.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
package utils
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/cosmos/evm/testutil/integration/os/factory"
"github.com/cosmos/evm/testutil/integration/os/network"
erc20types "github.com/cosmos/evm/x/erc20/types"
errorsmod "cosmossdk.io/errors"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)
// ERC20RegistrationData is the necessary data to provide in order to register an ERC20 token.
type ERC20RegistrationData struct {
// Addresses are the addresses of the ERC20 tokens.
Addresses []string
// ProposerPriv is the private key used to sign the proposal and voting transactions.
ProposerPriv cryptotypes.PrivKey
}
// ValidateBasic does stateless validation of the data for the ERC20 registration.
func (ed ERC20RegistrationData) ValidateBasic() error {
emptyAddr := common.Address{}
if len(ed.Addresses) == 0 {
return fmt.Errorf("addresses cannot be empty")
}
for _, a := range ed.Addresses {
if ok := common.IsHexAddress(a); !ok {
return fmt.Errorf("invalid address %s", a)
}
hexAddr := common.HexToAddress(a)
if hexAddr.Hex() == emptyAddr.Hex() {
return fmt.Errorf("address cannot be empty")
}
}
if ed.ProposerPriv == nil {
return fmt.Errorf("proposer private key cannot be nil")
}
return nil
}
// RegisterERC20 is a helper function to register ERC20 token through
// submitting a governance proposal and having it pass.
// It returns the registered token pair.
func RegisterERC20(tf factory.TxFactory, network network.Network, data ERC20RegistrationData) (res []erc20types.TokenPair, err error) {
err = data.ValidateBasic()
if err != nil {
return nil, errorsmod.Wrap(err, "failed to validate erc20 registration data")
}
proposal := erc20types.MsgRegisterERC20{
Signer: authtypes.NewModuleAddress("gov").String(),
Erc20Addresses: data.Addresses,
}
// Submit the proposal
proposalID, err := SubmitProposal(tf, network, data.ProposerPriv, fmt.Sprintf("Register %d Token", len(data.Addresses)), &proposal)
if err != nil {
return nil, errorsmod.Wrap(err, "failed to submit proposal")
}
err = network.NextBlock()
if err != nil {
return nil, errorsmod.Wrap(err, "failed to commit block after proposal")
}
// vote 'yes' and wait till proposal passes
err = ApproveProposal(tf, network, data.ProposerPriv, proposalID)
if err != nil {
return nil, errorsmod.Wrap(err, "failed to approve proposal")
}
// Check if token pair is registered
eq := network.GetERC20Client()
for _, a := range data.Addresses {
tokenPairRes, err := eq.TokenPair(network.GetContext(), &erc20types.QueryTokenPairRequest{Token: a})
if err != nil {
return nil, errorsmod.Wrap(err, "failed to query token pair")
}
res = append(res, tokenPairRes.TokenPair)
}
return res, nil
}
// ToggleTokenConversion is a helper function to toggle an ERC20 token pair conversion through
// submitting a governance proposal and having it pass.
func ToggleTokenConversion(tf factory.TxFactory, network network.Network, privKey cryptotypes.PrivKey, token string) error {
proposal := erc20types.MsgToggleConversion{
Authority: authtypes.NewModuleAddress("gov").String(),
Token: token,
}
// Submit the proposal
proposalID, err := SubmitProposal(tf, network, privKey, fmt.Sprintf("Toggle %s Token", token), &proposal)
if err != nil {
return errorsmod.Wrap(err, "failed to submit proposal")
}
err = network.NextBlock()
if err != nil {
return errorsmod.Wrap(err, "failed to commit block after proposal")
}
return ApproveProposal(tf, network, privKey, proposalID)
}