abi decoding of simple custom errors

Only supports errors without arguments for now
This commit is contained in:
Mark Spanbroek 2024-03-19 09:39:32 +01:00 committed by markspanbroek
parent 875900b493
commit 6b57e56a39
3 changed files with 48 additions and 0 deletions

17
ethers/errors.nim Normal file
View File

@ -0,0 +1,17 @@
import pkg/contractabi/selector
import ./basics
type SolidityError* = object of EthersError
{.push raises:[].}
template errors*(types) {.pragma.}
func decode*[E: SolidityError](_: type E, data: seq[byte]): ?!(ref E) =
const name = $E
const selector = selector(name, typeof(()))
if data.len < 4:
return failure "unable to decode " & name & ": signature too short"
if selector.toArray[0..<4] != data[0..<4]:
return failure "unable to decode " & name & ": signature doesn't match"
success (ref E)()

View File

@ -7,5 +7,6 @@ import ./testWallet
import ./testTesting
import ./testErc20
import ./testGasEstimation
import ./testErrorDecoding
{.warning[UnusedImport]:off.}

View File

@ -0,0 +1,30 @@
import std/unittest
import pkg/questionable/results
import pkg/ethers/errors
suite "Decoding of custom errors":
type SimpleError = object of SolidityError
test "decodes a simple error":
let decoded = SimpleError.decode(@[0xc2'u8, 0xbb, 0x94, 0x7c])
check decoded is ?!(ref SimpleError)
check decoded.isSuccess
check (!decoded) != nil
test "returns failure when decoding fails":
let invalid = @[0xc2'u8, 0xbb, 0x94, 0x0] # last byte is wrong
let decoded = SimpleError.decode(invalid)
check decoded.isFailure
test "returns failure when data is less than 4 bytes":
let invalid = @[0xc2'u8, 0xbb, 0x94]
let decoded = SimpleError.decode(invalid)
check decoded.isFailure
test "decoding only works for SolidityErrors":
type InvalidError = ref object of CatchableError
const works = compiles:
InvalidError.decode(@[0x1'u8, 0x2, 0x3, 0x4])
check not works