github.com/XinFinOrg/XDPoSChain@v1.6.0/XDCx/token.go (about)

     1  package XDCx
     2  
     3  import (
     4  	"math/big"
     5  	"strings"
     6  
     7  	"github.com/XinFinOrg/XDPoSChain/contracts/XDCx/contract"
     8  	"github.com/XinFinOrg/XDPoSChain/core"
     9  	"github.com/XinFinOrg/XDPoSChain/log"
    10  
    11  	"github.com/XinFinOrg/XDPoSChain"
    12  	"github.com/XinFinOrg/XDPoSChain/accounts/abi"
    13  	"github.com/XinFinOrg/XDPoSChain/common"
    14  	"github.com/XinFinOrg/XDPoSChain/consensus"
    15  	"github.com/XinFinOrg/XDPoSChain/core/state"
    16  )
    17  
    18  // GetTokenAbi return token abi
    19  func GetTokenAbi() (*abi.ABI, error) {
    20  	contractABI, err := abi.JSON(strings.NewReader(contract.TRC21ABI))
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  	return &contractABI, nil
    25  }
    26  
    27  // RunContract run smart contract
    28  func RunContract(chain consensus.ChainContext, statedb *state.StateDB, contractAddr common.Address, abi *abi.ABI, method string, args ...interface{}) (interface{}, error) {
    29  	input, err := abi.Pack(method)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	fakeCaller := common.HexToAddress("0x0000000000000000000000000000000000000001")
    34  	msg := XDPoSChain.CallMsg{To: &contractAddr, Data: input, From: fakeCaller}
    35  	result, err := core.CallContractWithState(msg, chain, statedb)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	var unpackResult interface{}
    40  	err = abi.Unpack(&unpackResult, method, result)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	return unpackResult, nil
    45  }
    46  
    47  func (XDCx *XDCX) GetTokenDecimal(chain consensus.ChainContext, statedb *state.StateDB, tokenAddr common.Address) (*big.Int, error) {
    48  	if tokenDecimal, ok := XDCx.tokenDecimalCache.Get(tokenAddr); ok {
    49  		return tokenDecimal.(*big.Int), nil
    50  	}
    51  	if tokenAddr.String() == common.XDCNativeAddress {
    52  		XDCx.tokenDecimalCache.Add(tokenAddr, common.BasePrice)
    53  		return common.BasePrice, nil
    54  	}
    55  	var decimals uint8
    56  	defer func() {
    57  		log.Debug("GetTokenDecimal from ", "relayerSMC", common.RelayerRegistrationSMC, "tokenAddr", tokenAddr.Hex(), "decimals", decimals)
    58  	}()
    59  	contractABI, err := GetTokenAbi()
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	stateCopy := statedb.Copy()
    64  	result, err := RunContract(chain, stateCopy, tokenAddr, contractABI, "decimals")
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	decimals = result.(uint8)
    69  
    70  	tokenDecimal := new(big.Int).SetUint64(0).Exp(big.NewInt(10), big.NewInt(int64(decimals)), nil)
    71  	XDCx.tokenDecimalCache.Add(tokenAddr, tokenDecimal)
    72  	return tokenDecimal, nil
    73  }
    74  
    75  // FIXME: using in unit tests only
    76  func (XDCx *XDCX) SetTokenDecimal(token common.Address, decimal *big.Int) {
    77  	XDCx.tokenDecimalCache.Add(token, decimal)
    78  }