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  }