Support calculation of solidity function selectors
This commit is contained in:
parent
e3c9aa4368
commit
ad3d2f7a4b
|
@ -1,5 +1,7 @@
|
|||
import contractabi/encoding
|
||||
import contractabi/decoding
|
||||
import contractabi/selector
|
||||
|
||||
export encoding
|
||||
export decoding
|
||||
export selector
|
||||
|
|
|
@ -5,5 +5,6 @@ license = "MIT"
|
|||
|
||||
requires "stint"
|
||||
requires "stew"
|
||||
requires "nimcrypto >= 0.5.4 & < 0.6.0"
|
||||
requires "questionable >= 0.10.0 & < 0.11.0"
|
||||
requires "upraises >= 0.1.0 & < 0.2.0"
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
import std/strutils
|
||||
import pkg/nimcrypto
|
||||
import pkg/stint
|
||||
import pkg/stew/byteutils
|
||||
import ./address
|
||||
|
||||
export address
|
||||
export stint
|
||||
|
||||
type FunctionSelector* = distinct array[4, byte]
|
||||
|
||||
proc toArray*(selector: FunctionSelector): array[4, byte] =
|
||||
array[4, byte](selector)
|
||||
|
||||
proc `$`*(selector: FunctionSelector): string =
|
||||
"0x" & selector.toArray.toHex
|
||||
|
||||
template solidityType(T: type, s: string) =
|
||||
func solidityType*(_: type T): string = s
|
||||
|
||||
solidityType uint8, "uint8"
|
||||
solidityType uint16, "uint16"
|
||||
solidityType uint32, "uint32"
|
||||
solidityType uint64, "uint64"
|
||||
solidityType UInt128, "uint128"
|
||||
solidityType UInt256, "uint256"
|
||||
solidityType int8, "int8"
|
||||
solidityType int16, "int16"
|
||||
solidityType int32, "int32"
|
||||
solidityType int64, "int64"
|
||||
solidityType Int128, "int128"
|
||||
solidityType Int256, "int256"
|
||||
solidityType bool, "bool"
|
||||
solidityType string, "string"
|
||||
solidityType Address, "address"
|
||||
|
||||
func solidityType*[N: static int](_: type array[N, byte]): string =
|
||||
"bytes" & $N
|
||||
|
||||
func solidityType*(_: type seq[byte]): string =
|
||||
"bytes"
|
||||
|
||||
func solidityType*[T, N](_: type array[N, T]): string =
|
||||
solidityType(T) & "[" & $array[N, T].default.len & "]"
|
||||
|
||||
func solidityType*[T](_: type seq[T]): string =
|
||||
solidityType(T) & "[]"
|
||||
|
||||
func solidityType*(Tuple: type tuple): string =
|
||||
var names: seq[string]
|
||||
for parameter in Tuple.default.fields:
|
||||
names.add(solidityType(typeof parameter))
|
||||
"(" & names.join(",") & ")"
|
||||
|
||||
func signature*(function: string, Parameters: type tuple = ()): string =
|
||||
function & solidityType(Parameters)
|
||||
|
||||
func hash(s: string): array[32, byte] =
|
||||
keccak256.digest(s.toBytes).data
|
||||
|
||||
func selector*(function: string, parameters: type tuple): FunctionSelector =
|
||||
let signature = signature(function, parameters)
|
||||
let hash = hash(signature)
|
||||
var selector: array[4, byte]
|
||||
selector[0..<4] = hash[0..<4]
|
||||
FunctionSelector(selector)
|
|
@ -0,0 +1,31 @@
|
|||
import std/unittest
|
||||
import pkg/contractabi/selector
|
||||
|
||||
suite "function selector":
|
||||
|
||||
test "translates nim types into solidity types":
|
||||
check solidityType(uint8) == "uint8"
|
||||
check solidityType(uint16) == "uint16"
|
||||
check solidityType(uint32) == "uint32"
|
||||
check solidityType(uint64) == "uint64"
|
||||
check solidityType(UInt128) == "uint128"
|
||||
check solidityType(UInt256) == "uint256"
|
||||
check solidityType(int8) == "int8"
|
||||
check solidityType(int16) == "int16"
|
||||
check solidityType(int32) == "int32"
|
||||
check solidityType(int64) == "int64"
|
||||
check solidityType(Int128) == "int128"
|
||||
check solidityType(Int256) == "int256"
|
||||
check solidityType(bool) == "bool"
|
||||
check solidityType(string) == "string"
|
||||
check solidityType(Address) == "address"
|
||||
check solidityType(array[4, byte]) == "bytes4"
|
||||
check solidityType(array[16, byte]) == "bytes16"
|
||||
check solidityType(seq[byte]) == "bytes"
|
||||
check solidityType(array[4, string]) == "string[4]"
|
||||
check solidityType(seq[string]) == "string[]"
|
||||
check solidityType((Address, string, bool)) == "(address,string,bool)"
|
||||
|
||||
test "calculates solidity function selector":
|
||||
check $selector("transfer", (Address, UInt256)) == "0xa9059cbb"
|
||||
check $selector("transferFrom", (Address, Address, UInt256)) == "0x23b872dd"
|
|
@ -2,5 +2,6 @@ import ./contractabi/testAddress
|
|||
import ./contractabi/testEncoding
|
||||
import ./contractabi/testDecoding
|
||||
import ./contractabi/testCustomTypes
|
||||
import ./contractabi/testSelector
|
||||
|
||||
{.warning[UnusedImport]:off.}
|
||||
|
|
Loading…
Reference in New Issue