2021-11-30 15:14:57 +01:00
|
|
|
import std/unittest
|
|
|
|
import contractabi
|
|
|
|
import ./examples
|
|
|
|
|
|
|
|
suite "ABI decoding":
|
|
|
|
|
|
|
|
proc checkDecode[T](value: T) =
|
|
|
|
let encoded = AbiEncoder.encode(value)
|
|
|
|
check AbiDecoder.decode(encoded, T) == value
|
|
|
|
|
|
|
|
proc checkDecode(T: type) =
|
|
|
|
checkDecode(T.example)
|
|
|
|
checkDecode(T.low)
|
|
|
|
checkDecode(T.high)
|
|
|
|
|
|
|
|
test "decodes uint8, uint16, 32, 64":
|
|
|
|
checkDecode(uint8)
|
|
|
|
checkDecode(uint16)
|
|
|
|
checkDecode(uint32)
|
|
|
|
checkDecode(uint64)
|
|
|
|
|
|
|
|
# TODO: failure to decode when prefix not all zeroes
|
|
|
|
# TODO: failure when trailing bytes
|
|
|
|
|
|
|
|
test "decodes booleans":
|
|
|
|
checkDecode(false)
|
|
|
|
checkDecode(true)
|
|
|
|
|
|
|
|
# TODO: failure to decode when value not 0 or 1
|
|
|
|
|
|
|
|
test "decodes ranges":
|
|
|
|
type SomeRange = range[0x0000'u16..0xAAAA'u16]
|
|
|
|
checkDecode(SomeRange(42))
|
|
|
|
checkDecode(SomeRange.low)
|
|
|
|
checkDecode(SomeRange.high)
|
|
|
|
|
|
|
|
# TODO: failure to decode when value not in range
|
|
|
|
|
|
|
|
test "decodes enums":
|
|
|
|
type SomeEnum = enum
|
|
|
|
one = 1
|
|
|
|
two = 2
|
|
|
|
checkDecode(one)
|
|
|
|
checkDecode(two)
|
|
|
|
|
|
|
|
# TODO: failure to decode when invalid enum value
|
|
|
|
|
|
|
|
test "decodes stints":
|
|
|
|
checkDecode(UInt128)
|
|
|
|
checkDecode(UInt256)
|
|
|
|
|
|
|
|
test "decodes byte arrays":
|
|
|
|
checkDecode([1'u8, 2'u8, 3'u8])
|
|
|
|
checkDecode(array[32, byte].example)
|
|
|
|
checkDecode(array[33, byte].example)
|
|
|
|
|
|
|
|
# TODO: failure to decode when byte array of wrong length
|
|
|
|
|
|
|
|
test "decodes byte sequences":
|
|
|
|
checkDecode(@[1'u8, 2'u8, 3'u8])
|
|
|
|
checkDecode(@(array[32, byte].example))
|
|
|
|
checkDecode(@(array[33, byte].example))
|
|
|
|
|
|
|
|
# TODO: failure to decode when not enough bytes
|
|
|
|
|
|
|
|
test "decodes tuples":
|
|
|
|
let a = true
|
|
|
|
let b = @[1'u8, 2'u8, 3'u8]
|
|
|
|
let c = 0xAABBCCDD'u32
|
|
|
|
let d = @[4'u8, 5'u8, 6'u8]
|
|
|
|
|
|
|
|
var encoder= AbiEncoder.init()
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.write(a)
|
|
|
|
encoder.write(b)
|
|
|
|
encoder.write(c)
|
|
|
|
encoder.write(d)
|
|
|
|
encoder.finishTuple()
|
|
|
|
let encoding = encoder.finish()
|
|
|
|
|
|
|
|
var decoder = AbiDecoder.init(encoding)
|
|
|
|
decoder.startTuple(dynamic=true)
|
|
|
|
check decoder.read(bool) == a
|
|
|
|
check decoder.read(seq[byte]) == b
|
|
|
|
check decoder.read(uint32) == c
|
|
|
|
check decoder.read(seq[byte]) == d
|
|
|
|
decoder.finishTuple()
|
|
|
|
decoder.finish()
|
|
|
|
|
|
|
|
test "decodes nested tuples":
|
|
|
|
let a = true
|
|
|
|
let b = @[1'u8, 2'u8, 3'u8]
|
|
|
|
let c = 0xAABBCCDD'u32
|
|
|
|
let d = @[4'u8, 5'u8, 6'u8]
|
|
|
|
|
|
|
|
var encoder= AbiEncoder.init()
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.write(a)
|
|
|
|
encoder.write(b)
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.write(c)
|
|
|
|
encoder.write(d)
|
|
|
|
encoder.finishTuple()
|
|
|
|
encoder.finishTuple()
|
|
|
|
let encoding = encoder.finish()
|
|
|
|
|
|
|
|
var decoder = AbiDecoder.init(encoding)
|
|
|
|
decoder.startTuple(dynamic=true)
|
|
|
|
check decoder.read(bool) == a
|
|
|
|
check decoder.read(seq[byte]) == b
|
|
|
|
decoder.startTuple(dynamic=true)
|
|
|
|
check decoder.read(uint32) == c
|
|
|
|
check decoder.read(seq[byte]) == d
|
|
|
|
decoder.finishTuple()
|
|
|
|
decoder.finishTuple()
|
|
|
|
decoder.finish()
|
|
|
|
|
|
|
|
test "reads elements after dynamic tuple":
|
|
|
|
let a = @[1'u8, 2'u8, 3'u8]
|
|
|
|
let b = 0xAABBCCDD'u32
|
|
|
|
var encoder = AbiEncoder.init()
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.write(a)
|
|
|
|
encoder.finishTuple()
|
|
|
|
encoder.write(b)
|
|
|
|
let encoding = encoder.finish()
|
|
|
|
|
|
|
|
var decoder = AbiDecoder.init(encoding)
|
|
|
|
decoder.startTuple(dynamic=true)
|
|
|
|
check decoder.read(seq[byte]) == a
|
|
|
|
decoder.finishTuple()
|
|
|
|
check decoder.read(uint32) == b
|
|
|
|
decoder.finish()
|
|
|
|
|
|
|
|
test "reads elements after static tuple":
|
|
|
|
let a = 0x123'u16
|
|
|
|
let b = 0xAABBCCDD'u32
|
|
|
|
var encoder = AbiEncoder.init()
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.write(a)
|
|
|
|
encoder.finishTuple()
|
|
|
|
encoder.write(b)
|
|
|
|
let encoding = encoder.finish()
|
|
|
|
|
|
|
|
var decoder = AbiDecoder.init(encoding)
|
|
|
|
decoder.startTuple(dynamic=false)
|
|
|
|
check decoder.read(uint16) == a
|
|
|
|
decoder.finishTuple()
|
|
|
|
check decoder.read(uint32) == b
|
|
|
|
decoder.finish()
|
|
|
|
|
|
|
|
test "reads static tuple inside dynamic tuple":
|
|
|
|
let a = @[1'u8, 2'u8, 3'u8]
|
|
|
|
let b = 0xAABBCCDD'u32
|
|
|
|
|
|
|
|
var encoder= AbiEncoder.init()
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.write(a)
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.write(b)
|
|
|
|
encoder.finishTuple()
|
|
|
|
encoder.finishTuple()
|
|
|
|
let encoding = encoder.finish()
|
|
|
|
|
|
|
|
var decoder = AbiDecoder.init(encoding)
|
|
|
|
decoder.startTuple(dynamic=true)
|
|
|
|
check decoder.read(seq[byte]) == a
|
|
|
|
decoder.startTuple(dynamic=false)
|
|
|
|
check decoder.read(uint32) == b
|
|
|
|
decoder.finishTuple()
|
|
|
|
decoder.finishTuple()
|
|
|
|
decoder.finish()
|
|
|
|
|
|
|
|
test "reads empty tuples":
|
|
|
|
var encoder = AbiEncoder.init()
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.startTuple()
|
|
|
|
encoder.finishTuple()
|
|
|
|
encoder.finishTuple()
|
|
|
|
let encoding = encoder.finish()
|
|
|
|
|
|
|
|
var decoder = AbiDecoder.init(encoding)
|
|
|
|
decoder.startTuple(dynamic=false)
|
|
|
|
decoder.startTuple(dynamic=false)
|
|
|
|
decoder.finishTuple()
|
|
|
|
decoder.finishTuple()
|
|
|
|
decoder.finish()
|
|
|
|
|
2021-11-30 16:22:52 +01:00
|
|
|
test "decodes sequences":
|
|
|
|
checkDecode(@[seq[byte].example, seq[byte].example])
|
|
|
|
|
|
|
|
test "decodes arrays with static elements":
|
|
|
|
checkDecode([array[32, byte].example, array[32, byte].example])
|
|
|
|
|
|
|
|
test "decodes arrays with dynamic elements":
|
|
|
|
checkDecode([seq[byte].example, seq[byte].example])
|
|
|
|
|