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 }