description: Collection of useful Ethereum utility functions in Go.

Collection of Utility Functions

The utility functions’ implementation are found below in the full code section. They are generous in what they accept. Here we’ll be showing examples of usage.

Derive the Ethereum public address from a public key:

  1. publicKeyBytes, _ := hex.DecodeString("049a7df67f79246283fdc93af76d4f8cdd62c4886e8cd870944e817dd0b97934fdd7719d0810951e03418205868a5c1b40b192451367f28e0088dd75e15de40c05")
  2. address := util.PublicKeyBytesToAddress(publicKeyBytes)
  3. fmt.Println(address.Hex()) // 0x96216849c49358B10257cb55b28eA603c874b05E

Check if an address is a valid Ethereum address:

  1. valid := util.IsValidAddress("0x323b5d4c32345ced77393b3530b1eed0f346429d")
  2. fmt.Println(valid) // true

Check if an address is a zero address.

  1. zeroed := util.IsZeroAddress("0x0")
  2. fmt.Println(zeroed) // true

Convert a decimal to wei. The second argument is the number of decimals.

  1. wei := util.ToWei(0.02, 18)
  2. fmt.Println(wei) // 20000000000000000

Convert wei to decimals. The second argument is the number of decimals.

  1. wei := new(big.Int)
  2. wei.SetString("20000000000000000", 10)
  3. eth := util.ToDecimal(wei, 18)
  4. fmt.Println(eth) // 0.02

Calculate the gas cost given the gas limit and gas price.

  1. gasLimit := uint64(21000)
  2. gasPrice := new(big.Int)
  3. gasPrice.SetString("2000000000", 10)
  4. gasCost := util.CalcGasCost(gasLimit, gasPrice)
  5. fmt.Println(gasCost) // 42000000000000

Retrieve the R, S, and V values from a signature.

  1. sig := "0x789a80053e4927d0a898db8e065e948f5cf086e32f9ccaa54c1908e22ac430c62621578113ddbb62d509bf6049b8fb544ab06d36f916685a2eb8e57ffadde02301"
  2. r, s, v := util.SigRSV(sig)
  3. fmt.Println(hexutil.Encode(r[:])[2:]) // 789a80053e4927d0a898db8e065e948f5cf086e32f9ccaa54c1908e22ac430c6
  4. fmt.Println(hexutil.Encode(s[:])[2:]) // 2621578113ddbb62d509bf6049b8fb544ab06d36f916685a2eb8e57ffadde023
  5. fmt.Println(v) // 28

Full code

util.go

  1. package util
  2. import (
  3. "math/big"
  4. "reflect"
  5. "regexp"
  6. "strconv"
  7. "github.com/ethereum/go-ethereum/common"
  8. "github.com/ethereum/go-ethereum/common/hexutil"
  9. "github.com/shopspring/decimal"
  10. )
  11. // IsValidAddress validate hex address
  12. func IsValidAddress(iaddress interface{}) bool {
  13. re := regexp.MustCompile("^0x[0-9a-fA-F]{40}$")
  14. switch v := iaddress.(type) {
  15. case string:
  16. return re.MatchString(v)
  17. case common.Address:
  18. return re.MatchString(v.Hex())
  19. default:
  20. return false
  21. }
  22. }
  23. // IsZeroAddress validate if it's a 0 address
  24. func IsZeroAddress(iaddress interface{}) bool {
  25. var address common.Address
  26. switch v := iaddress.(type) {
  27. case string:
  28. address = common.HexToAddress(v)
  29. case common.Address:
  30. address = v
  31. default:
  32. return false
  33. }
  34. zeroAddressBytes := common.FromHex("0x0000000000000000000000000000000000000000")
  35. addressBytes := address.Bytes()
  36. return reflect.DeepEqual(addressBytes, zeroAddressBytes)
  37. }
  38. // ToDecimal wei to decimals
  39. func ToDecimal(ivalue interface{}, decimals int) decimal.Decimal {
  40. value := new(big.Int)
  41. switch v := ivalue.(type) {
  42. case string:
  43. value.SetString(v, 10)
  44. case *big.Int:
  45. value = v
  46. }
  47. mul := decimal.NewFromFloat(float64(10)).Pow(decimal.NewFromFloat(float64(decimals)))
  48. num, _ := decimal.NewFromString(value.String())
  49. result := num.Div(mul)
  50. return result
  51. }
  52. // ToWei decimals to wei
  53. func ToWei(iamount interface{}, decimals int) *big.Int {
  54. amount := decimal.NewFromFloat(0)
  55. switch v := iamount.(type) {
  56. case string:
  57. amount, _ = decimal.NewFromString(v)
  58. case float64:
  59. amount = decimal.NewFromFloat(v)
  60. case int64:
  61. amount = decimal.NewFromFloat(float64(v))
  62. case decimal.Decimal:
  63. amount = v
  64. case *decimal.Decimal:
  65. amount = *v
  66. }
  67. mul := decimal.NewFromFloat(float64(10)).Pow(decimal.NewFromFloat(float64(decimals)))
  68. result := amount.Mul(mul)
  69. wei := new(big.Int)
  70. wei.SetString(result.String(), 10)
  71. return wei
  72. }
  73. // CalcGasCost calculate gas cost given gas limit (units) and gas price (wei)
  74. func CalcGasCost(gasLimit uint64, gasPrice *big.Int) *big.Int {
  75. gasLimitBig := big.NewInt(int64(gasLimit))
  76. return gasLimitBig.Mul(gasLimitBig, gasPrice)
  77. }
  78. // SigRSV signatures R S V returned as arrays
  79. func SigRSV(isig interface{}) ([32]byte, [32]byte, uint8) {
  80. var sig []byte
  81. switch v := isig.(type) {
  82. case []byte:
  83. sig = v
  84. case string:
  85. sig, _ = hexutil.Decode(v)
  86. }
  87. sigstr := common.Bytes2Hex(sig)
  88. rS := sigstr[0:64]
  89. sS := sigstr[64:128]
  90. R := [32]byte{}
  91. S := [32]byte{}
  92. copy(R[:], common.FromHex(rS))
  93. copy(S[:], common.FromHex(sS))
  94. vStr := sigstr[128:130]
  95. vI, _ := strconv.Atoi(vStr)
  96. V := uint8(vI + 27)
  97. return R, S, V
  98. }

test file: util_test.go