-
Notifications
You must be signed in to change notification settings - Fork 0
/
bank.go
129 lines (115 loc) · 3.7 KB
/
bank.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
package keeper
import (
"math/big"
"strings"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/common"
blackfury "github.com/fanfury-sports/blackfury/types"
"github.com/fanfury-sports/blackfury/x/erc20/types"
"github.com/tharsis/evmos/v4/contracts"
)
func (k Keeper) IsDenomForErc20(denom string) bool {
denomSplit := strings.Split(denom, "/")
if len(denomSplit) != 2 {
return false
}
if denomSplit[0] != types.DenomPrefix {
return false
}
return common.IsHexAddress(denomSplit[1])
}
func (k Keeper) getContractByDenom(ctx sdk.Context, denom string) (common.Address, bool) {
denomSplit := strings.Split(denom, "/")
if len(denomSplit) == 2 && denomSplit[0] == types.DenomPrefix && common.IsHexAddress(denomSplit[1]) {
return common.HexToAddress(denomSplit[1]), true
} else {
id := k.GetTokenPairID(ctx, denom)
if len(id) == 0 {
return common.Address{}, false
}
pair, found := k.GetTokenPair(ctx, id)
if !found {
panic(sdkerrors.Wrapf(types.ErrTokenPairNotFound, "token pair '%s' with denom '%s' not found", id, denom))
}
return pair.GetERC20Contract(), true
}
}
func (k Keeper) GetSupply(ctx sdk.Context, denom string) sdk.Coin {
contract, found := k.getContractByDenom(ctx, denom)
if !found {
return sdk.Coin{}
}
amt, err := k.totalSupply(ctx, contract)
if err != nil {
return sdk.Coin{}
}
return sdk.NewCoin(denom, sdk.NewIntFromBigInt(amt))
}
func (k Keeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin {
contract, found := k.getContractByDenom(ctx, denom)
if !found {
return sdk.Coin{}
}
amt, err := k.balanceOf(ctx, contract, common.BytesToAddress(addr))
if err != nil {
return sdk.Coin{}
}
return sdk.NewCoin(denom, sdk.NewIntFromBigInt(amt))
}
func (k Keeper) SplitCoinsByErc20(amt sdk.Coins) (nativeCoins sdk.Coins, nativeErc20Tokens sdk.Coins) {
for _, coin := range amt {
if k.IsDenomForErc20(coin.Denom) {
nativeErc20Tokens = nativeErc20Tokens.Add(coin)
} else {
nativeCoins = nativeCoins.Add(coin)
}
}
return
}
func (k Keeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, nativeCoins sdk.Coins, nativeErc20Tokens sdk.Coins) (err error) {
erc20 := contracts.ERC20MinterBurnerDecimalsContract.ABI
from := common.BytesToAddress(fromAddr)
to := common.BytesToAddress(toAddr)
var tokenContracts []common.Address
var amounts []*big.Int
for _, coin := range nativeCoins {
if strings.Contains(coin.Denom, blackfury.DisplayDenom) {
// Do not touch gas token
continue
}
id := k.GetTokenPairID(ctx, coin.Denom)
if len(id) == 0 {
return sdkerrors.Wrapf(types.ErrTokenPairNotFound, "token pair with denom '%s' not found", coin.Denom)
}
pair, found := k.GetTokenPair(ctx, id)
if !found {
panic(sdkerrors.Wrapf(types.ErrTokenPairNotFound, "token pair '%s' with denom '%s' not found", id, coin.Denom))
}
tokenContracts = append(tokenContracts, pair.GetERC20Contract())
amounts = append(amounts, coin.Amount.BigInt())
}
for _, coin := range nativeErc20Tokens {
denomSplit := strings.Split(coin.Denom, "/")
contract := common.HexToAddress(denomSplit[1]) // had checked preceding
tokenContracts = append(tokenContracts, contract)
amounts = append(amounts, coin.Amount.BigInt())
}
for i, contract := range tokenContracts {
amt := amounts[i]
if len(fromAddr) == 0 {
// Mint
_, err = k.CallEVM(ctx, erc20, types.ModuleAddress, contract, "mint", to, amt)
} else if len(toAddr) == 0 {
// Burn
_, err = k.CallEVM(ctx, erc20, from, contract, "burn", amt)
} else {
// Transfer
_, err = k.CallEVM(ctx, erc20, from, contract, "transfer", to, amt)
}
if err != nil {
return err
}
}
return nil
}