github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/erc20/keeper/keeper.go (about) 1 package keeper 2 3 import ( 4 "fmt" 5 6 "github.com/ethereum/go-ethereum/common" 7 8 ethermint "github.com/fibonacci-chain/fbc/app/types" 9 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 10 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 11 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 12 "github.com/fibonacci-chain/fbc/x/erc20/types" 13 "github.com/fibonacci-chain/fbc/x/params" 14 ) 15 16 // Keeper wraps the CommitStateDB, allowing us to pass in SDK context while adhering 17 // to the StateDB interface. 18 type Keeper struct { 19 cdc *codec.Codec 20 storeKey sdk.StoreKey 21 paramSpace Subspace 22 accountKeeper AccountKeeper 23 supplyKeeper SupplyKeeper 24 bankKeeper BankKeeper 25 govKeeper GovKeeper 26 evmKeeper EvmKeeper 27 transferKeeper TransferKeeper 28 } 29 30 // NewKeeper generates new erc20 module keeper 31 func NewKeeper( 32 cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace, 33 ak AccountKeeper, sk SupplyKeeper, bk BankKeeper, 34 ek EvmKeeper, tk TransferKeeper) Keeper { 35 // set KeyTable if it has not already been set 36 if !paramSpace.HasKeyTable() { 37 paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) 38 } 39 40 return Keeper{ 41 cdc: cdc, 42 storeKey: storeKey, 43 paramSpace: paramSpace, 44 accountKeeper: ak, 45 supplyKeeper: sk, 46 bankKeeper: bk, 47 evmKeeper: ek, 48 transferKeeper: tk, 49 } 50 } 51 52 // Logger returns a module-specific logger. 53 func (k Keeper) Logger(ctx sdk.Context) log.Logger { 54 return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) 55 } 56 57 // SetGovKeeper sets keeper of gov 58 func (k *Keeper) SetGovKeeper(gk GovKeeper) { 59 k.govKeeper = gk 60 } 61 62 // SetContractForDenom set the contract for native denom, 63 // 1. if any existing for denom, replace the old one. 64 // 2. if any existing for contract, return error. 65 func (k Keeper) SetContractForDenom(ctx sdk.Context, denom string, contract common.Address) error { 66 // check the contract is not registered already 67 _, found := k.GetDenomByContract(ctx, contract) 68 if found { 69 return types.ErrRegisteredContract(contract.String()) 70 } 71 72 store := ctx.KVStore(k.storeKey) 73 existingContract, found := k.GetContractByDenom(ctx, denom) 74 if found { 75 // delete existing mapping 76 store.Delete(types.ContractToDenomKey(existingContract.Bytes())) 77 } 78 store.Set(types.DenomToContractKey(denom), contract.Bytes()) 79 store.Set(types.ContractToDenomKey(contract.Bytes()), []byte(denom)) 80 return nil 81 } 82 83 // GetContracts returns all contract mappings 84 func (k Keeper) GetContracts(ctx sdk.Context) (out []types.TokenMapping) { 85 store := ctx.KVStore(k.storeKey) 86 iter := sdk.KVStorePrefixIterator(store, types.KeyPrefixDenomToContract) 87 88 for ; iter.Valid(); iter.Next() { 89 out = append(out, types.TokenMapping{ 90 Denom: string(iter.Key()), 91 Contract: common.BytesToAddress(iter.Value()).Hex(), 92 }) 93 } 94 return 95 } 96 97 // GetContractByDenom find the corresponding contract for the denom 98 func (k Keeper) GetContractByDenom(ctx sdk.Context, denom string) (contract common.Address, found bool) { 99 store := ctx.KVStore(k.storeKey) 100 bz := store.Get(types.DenomToContractKey(denom)) 101 if len(bz) == 0 { 102 return common.Address{}, false 103 } 104 return common.BytesToAddress(bz), true 105 } 106 107 // DeleteContractForDenom delete the contract mapping for native denom, 108 // returns false if mapping not exists. 109 func (k Keeper) DeleteContractForDenom(ctx sdk.Context, denom string) bool { 110 store := ctx.KVStore(k.storeKey) 111 existingContract, found := k.GetContractByDenom(ctx, denom) 112 if !found { 113 return false 114 } 115 store.Delete(types.ContractToDenomKey(existingContract.Bytes())) 116 store.Delete(types.DenomToContractKey(denom)) 117 return true 118 } 119 120 // GetDenomByContract find native denom by contract address 121 func (k Keeper) GetDenomByContract(ctx sdk.Context, contract common.Address) (denom string, found bool) { 122 store := ctx.KVStore(k.storeKey) 123 bz := store.Get(types.ContractToDenomKey(contract.Bytes())) 124 if len(bz) == 0 { 125 return "", false 126 } 127 return string(bz), true 128 } 129 130 // IterateMapping iterates over all the stored mapping and performs a callback function 131 func (k Keeper) IterateMapping(ctx sdk.Context, cb func(denom, contract string) (stop bool)) { 132 store := ctx.KVStore(k.storeKey) 133 iterator := sdk.KVStorePrefixIterator(store, types.KeyPrefixContractToDenom) 134 135 defer iterator.Close() 136 for ; iterator.Valid(); iterator.Next() { 137 denom := string(iterator.Value()) 138 conotract := common.BytesToAddress(iterator.Key()).String() 139 140 if cb(denom, conotract) { 141 break 142 } 143 } 144 } 145 146 func (k Keeper) ProxyContractRedirect(ctx sdk.Context, denom string, tp types.RedirectType, addr common.Address) error { 147 err := k.redirectProxyContractInfoByTp(ctx, denom, addr, tp) 148 if err != nil { 149 return types.ErrProxyContractRedirect(denom, int(tp), addr.String()) 150 } 151 return nil 152 } 153 154 func (k Keeper) redirectProxyContractInfoByTp(ctx sdk.Context, denom string, contract common.Address, tp types.RedirectType) error { 155 method := "" 156 switch tp { 157 case types.RedirectImplementation: 158 method = types.ProxyContractUpgradeTo 159 case types.RedirectOwner: 160 method = types.ProxyContractChangeAdmin 161 default: 162 return fmt.Errorf("no such tp %d", tp) 163 } 164 contractProxy, found := k.GetContractByDenom(ctx, denom) 165 if !found { 166 return fmt.Errorf("GetContractByDenom contract not found,denom: %s", denom) 167 } 168 _, err := k.CallModuleERC20Proxy(ctx, contractProxy, method, contract) 169 170 return err 171 } 172 173 func (k Keeper) GetProxyTemplateContract(ctx sdk.Context) (types.CompiledContract, bool) { 174 return k.getTemplateContract(ctx, types.ProposalTypeContextTemplateProxy) 175 } 176 177 func (k Keeper) GetImplementTemplateContract(ctx sdk.Context) (types.CompiledContract, bool) { 178 return k.getTemplateContract(ctx, types.ProposalTypeContextTemplateImpl) 179 } 180 181 func (k Keeper) getTemplateContract(ctx sdk.Context, typeStr string) (types.CompiledContract, bool) { 182 store := ctx.KVStore(k.storeKey) 183 data := store.Get(types.ConstructContractKey(typeStr)) 184 if nil == data { 185 return types.CompiledContract{}, false 186 } 187 188 return types.MustUnmarshalCompileContract(data), true 189 } 190 191 func (k Keeper) InitInternalTemplateContract(ctx sdk.Context) { 192 k.SetTemplateContract(ctx, types.ProposalTypeContextTemplateImpl, string(types.GetInternalImplementationBytes())) 193 k.SetTemplateContract(ctx, types.ProposalTypeContextTemplateProxy, string(types.GetInternalProxyBytes())) 194 } 195 196 func (k Keeper) SetTemplateContract(ctx sdk.Context, typeStr string, str string) error { 197 store := ctx.KVStore(k.storeKey) 198 store.Set(types.ConstructContractKey(typeStr), []byte(str)) 199 return nil 200 } 201 202 // GetEthAccount returns an eth account. 203 func (k Keeper) GetEthAccount(ctx sdk.Context, addr common.Address) (*ethermint.EthAccount, bool) { 204 cosmosAddr := sdk.AccAddress(addr.Bytes()) 205 acct := k.accountKeeper.GetAccount(ctx, cosmosAddr) 206 if acct == nil { 207 return nil, false 208 } 209 210 ethAcct, _ := acct.(*ethermint.EthAccount) 211 return ethAcct, true 212 }