Support decoding of signed integers

This commit is contained in:
Mark Spanbroek 2021-12-09 10:38:34 +01:00
parent 8131170475
commit a0fad53523
4 changed files with 31 additions and 6 deletions

View File

@ -62,7 +62,7 @@ func skipPadding(decoder: var AbiDecoder, amount: int): ?!void =
let index = decoder.index
?decoder.advance(amount)
for i in index..<index+amount:
if decoder.bytes[i] != 0:
if decoder.bytes[i] notin [0x00'u8, 0xFF'u8]:
return failure "invalid padding found"
success()
@ -79,6 +79,23 @@ func read(decoder: var AbiDecoder, amount: int, padding=padLeft): ?!seq[byte] =
func decode(decoder: var AbiDecoder, T: type UInt): ?!T =
success T.fromBytesBE(?decoder.read(sizeof(T)))
template unsigned(T: type SomeSignedInt): type SomeUnsignedInt =
when T is int8: uint8
elif T is int16: uint16
elif T is int32: uint32
elif T is int64: uint64
else: {.error "unsupported signed integer type".}
func decode(decoder: var AbiDecoder, T: type SomeSignedInt): ?!T =
let bytes = ?decoder.read(sizeof(T))
let unsigned = T.unsigned.fromBytesBE(bytes)
let signed = cast[T](unsigned)
success signed
func decode[bits](decoder: var AbiDecoder, T: type StInt[bits]): ?!T =
let unsigned = ?decoder.read(StUint[bits])
success cast[T](unsigned)
template basetype(Range: type range): untyped =
when Range isnot SomeUnsignedInt: {.error: "only uint ranges supported".}
elif sizeof(Range) == sizeof(uint8): uint8

View File

@ -89,7 +89,7 @@ func encode[bits](encoder: var AbiEncoder, value: StInt[bits]) =
encoder.padleft(bytes, padding)
func encode(encoder: var AbiEncoder, value: SomeSignedInt) =
encoder.write(value.i256)
encoder.write(value.to(StInt[64]))
func encode(encoder: var AbiEncoder, value: bool) =
encoder.encode(if value: 1'u8 else: 0'u8)

View File

@ -18,8 +18,8 @@ proc example*[T](_: type seq[T], len = 0..5): seq[T] =
let chosenlen = rand(len)
newSeqWith(chosenlen, T.example)
proc example*(_: type UInt256): UInt256 =
UInt256.fromBytes(array[32, byte].example)
proc example*(T: type StUint): T =
T.fromBytes(array[sizeof(T), byte].example)
proc example*(_: type UInt128): UInt128 =
UInt128.fromBytes(array[16, byte].example)
proc example*(T: type StInt): T =
cast[T](StUint[T.bits].example)

View File

@ -20,6 +20,12 @@ suite "ABI decoding":
checkDecode(uint32)
checkDecode(uint64)
test "decodes int8, int16, int32, int64":
checkDecode(int8)
checkDecode(int16)
checkDecode(int32)
checkDecode(int64)
test "fails to decode when reading past end":
var encoded = AbiEncoder.encode(uint8.example)
encoded.delete(encoded.len-1)
@ -75,6 +81,8 @@ suite "ABI decoding":
test "decodes stints":
checkDecode(UInt128)
checkDecode(UInt256)
checkDecode(Int128)
checkDecode(Int256)
test "decodes byte arrays":
checkDecode([1'u8, 2'u8, 3'u8])