whitelist.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package service
  2. import (
  3. "bytes"
  4. "encoding/hex"
  5. "errors"
  6. "fmt"
  7. "github.com/ethereum/go-ethereum/accounts/abi"
  8. "github.com/ethereum/go-ethereum/common"
  9. "github.com/ethereum/go-ethereum/core/types"
  10. tronaddr "github.com/fbsobreira/gotron-sdk/pkg/address"
  11. troncore "github.com/fbsobreira/gotron-sdk/pkg/proto/core"
  12. "google.golang.org/protobuf/reflect/protoreflect"
  13. "math/big"
  14. )
  15. const (
  16. ethUsdt = "0xdAC17F958D2ee523a2206206994597C13D831ec7"
  17. ethUsdc = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
  18. tronUsdt = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
  19. tronUsdc = "TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8"
  20. )
  21. var (
  22. transferId, _ = hex.DecodeString("a9059cbb")
  23. approveId, _ = hex.DecodeString("095ea7b3")
  24. )
  25. var (
  26. addressTy, _ = abi.NewType("address", "", nil)
  27. uint256Ty, _ = abi.NewType("uint256", "", nil)
  28. arguments = abi.Arguments{{Type: addressTy}, {Type: uint256Ty}}
  29. )
  30. func checkErc(tx *types.Transaction, whitelists map[string]struct{}) (string, string, string, error) {
  31. if tx.To().String() == ethUsdt || tx.To().String() == ethUsdc {
  32. input := tx.Data()
  33. var methodId [4]byte
  34. copy(methodId[:], input[:4])
  35. if !(bytes.Equal(methodId[:], transferId) || bytes.Equal(methodId[:], approveId)) {
  36. return "", "", "", errors.New("erc20: only sign transfer and approve")
  37. }
  38. unpack, err := arguments.Unpack(input[4:])
  39. if err != nil {
  40. return "", "", "", err
  41. }
  42. to, ok := unpack[0].(common.Address)
  43. if !ok {
  44. return "", "", "", errors.New("erc20: to parameter error")
  45. }
  46. amount, ok := unpack[1].(*big.Int)
  47. if !ok {
  48. return "", "", "", errors.New("erc20: amount parameter error")
  49. }
  50. if _, exist := whitelists[to.String()]; !exist {
  51. return "", "", "", errors.New("erc20: to is not a whitelist address")
  52. }
  53. coin := usdtCoin
  54. if tx.To().String() == ethUsdc {
  55. coin = usdcCoin
  56. }
  57. return coin, to.String(), amount.String(), nil
  58. } else {
  59. if _, exist := whitelists[tx.To().String()]; !exist {
  60. return "", "", "", errors.New("eth: to is not a whitelist address")
  61. }
  62. }
  63. return ethCoin, tx.To().String(), tx.Value().String(), nil
  64. }
  65. func checkTron(tx *troncore.Transaction, whitelists map[string]struct{}) (string, string, string, error) {
  66. if len(tx.GetRawData().Contract) != 1 {
  67. return "", "", "", errors.New("Transaction_Contract length must be 1")
  68. }
  69. contract := tx.GetRawData().Contract[0]
  70. var c interface{}
  71. switch contract.Type {
  72. case troncore.Transaction_Contract_TransferContract:
  73. c = &troncore.TransferContract{}
  74. case troncore.Transaction_Contract_TriggerSmartContract:
  75. c = &troncore.TriggerSmartContract{}
  76. default:
  77. return "", "", "", errors.New("Transaction_Contract Type must be Transaction_Contract_TransferContract and Transaction_Contract_TriggerSmartContract")
  78. }
  79. if err := contract.GetParameter().UnmarshalTo(c.(protoreflect.ProtoMessage)); err != nil {
  80. return "", "", "", fmt.Errorf("proto unmarshal any: %+w", err)
  81. }
  82. if contract.Type == troncore.Transaction_Contract_TransferContract {
  83. transferContract := c.(*troncore.TransferContract)
  84. to := tronaddr.Address(transferContract.ToAddress)
  85. if _, exist := whitelists[to.String()]; !exist {
  86. return "", "", "", errors.New("trx: to is not a whitelist address")
  87. }
  88. return trxCoin, to.String(), big.NewInt(0).SetInt64(transferContract.Amount).String(), nil
  89. } else {
  90. triggerSmartContract := c.(*troncore.TriggerSmartContract)
  91. contractAddr := tronaddr.Address(triggerSmartContract.ContractAddress)
  92. if contractAddr.String() != tronUsdt && contractAddr.String() != tronUsdc {
  93. return "", "", "", errors.New("trc20: only sign usdt and usdc")
  94. }
  95. input := triggerSmartContract.Data
  96. var methodId [4]byte
  97. copy(methodId[:], input[:4])
  98. if !(bytes.Equal(methodId[:], transferId) || bytes.Equal(methodId[:], approveId)) {
  99. return "", "", "", errors.New("trc20: only sign transfer and approve")
  100. }
  101. unpack, err := arguments.Unpack(input[4:])
  102. if err != nil {
  103. return "", "", "", err
  104. }
  105. to, ok := unpack[0].(common.Address)
  106. if !ok {
  107. return "", "", "", errors.New("trc20: to parameter error")
  108. }
  109. amount, ok := unpack[1].(*big.Int)
  110. if !ok {
  111. return "", "", "", errors.New("erc20: amount parameter error")
  112. }
  113. toTron := make([]byte, 0)
  114. toTron = append(toTron, tronaddr.TronBytePrefix)
  115. toTron = append(toTron, to.Bytes()...)
  116. if _, exist := whitelists[tronaddr.Address(toTron).String()]; !exist {
  117. return "", "", "", errors.New("trc20: to is not a whitelist address")
  118. }
  119. coin := usdtCoin
  120. if contractAddr.String() == tronUsdc {
  121. coin = usdcCoin
  122. }
  123. return coin, to.String(), amount.String(), nil
  124. }
  125. }