nim-ethers/testmodule/testCustomErrors.nim

150 lines
5.2 KiB
Nim

import std/os
import pkg/serde
import pkg/asynctest
import pkg/ethers
import ./hardhat
suite "Contract custom errors":
type
TestCustomErrors = ref object of Contract
SimpleError = object of SolidityError
ErrorWithArguments = object of SolidityError
arguments: tuple[one: UInt256, two: bool]
ErrorWithStaticStruct = object of SolidityError
arguments: tuple[one: Static, two: Static]
ErrorWithDynamicStruct = object of SolidityError
arguments: tuple[one: Dynamic, two: Dynamic]
ErrorWithDynamicAndStaticStruct = object of SolidityError
arguments: tuple[one: Dynamic, two: Static]
Static = (UInt256, UInt256)
Dynamic = (string, UInt256)
var contract: TestCustomErrors
var provider: JsonRpcProvider
var snapshot: JsonNode
let providerUrl = getEnv("ETHERS_TEST_PROVIDER", "localhost:8545")
setup:
provider = JsonRpcProvider.new("http://" & providerUrl)
snapshot = await provider.send("evm_snapshot")
let deployment = readDeployment()
let address = !deployment.address(TestCustomErrors)
contract = TestCustomErrors.new(address, provider)
teardown:
discard await provider.send("evm_revert", @[snapshot])
await provider.close()
test "handles simple errors":
proc revertsSimpleError(contract: TestCustomErrors)
{.contract, pure, errors:[SimpleError].}
expect SimpleError:
await contract.revertsSimpleError()
test "handles error with arguments":
proc revertsErrorWithArguments(contract: TestCustomErrors)
{.contract, pure, errors:[ErrorWithArguments].}
try:
await contract.revertsErrorWithArguments()
fail()
except ErrorWithArguments as error:
check error.arguments.one == 1
check error.arguments.two == true
test "handles error with static struct arguments":
proc revertsErrorWithStaticStruct(contract: TestCustomErrors)
{.contract, pure, errors:[ErrorWithStaticStruct].}
try:
await contract.revertsErrorWithStaticStruct()
fail()
except ErrorWithStaticStruct as error:
check error.arguments.one == (1.u256, 2.u256)
check error.arguments.two == (3.u256, 4.u256)
test "handles error with dynamic struct arguments":
proc revertsErrorWithDynamicStruct(contract: TestCustomErrors)
{.contract, pure, errors:[ErrorWithDynamicStruct].}
try:
await contract.revertsErrorWithDynamicStruct()
fail()
except ErrorWithDynamicStruct as error:
check error.arguments.one == ("1", 2.u256)
check error.arguments.two == ("3", 4.u256)
test "handles error with dynamic and static struct arguments":
proc revertsErrorWithDynamicAndStaticStruct(contract: TestCustomErrors)
{.contract, pure, errors:[ErrorWithDynamicAndStaticStruct].}
try:
await contract.revertsErrorWithDynamicAndStaticStruct()
fail()
except ErrorWithDynamicAndStaticStruct as error:
check error.arguments.one == ("1", 2.u256)
check error.arguments.two == (3.u256, 4.u256)
test "handles multiple error types":
proc revertsMultipleErrors(contract: TestCustomErrors, simple: bool)
{.contract, errors:[SimpleError, ErrorWithArguments].}
let contract = contract.connect(provider.getSigner())
expect SimpleError:
await contract.revertsMultipleErrors(simple = true)
expect ErrorWithArguments:
await contract.revertsMultipleErrors(simple = false)
test "handles gas estimation errors":
proc revertsTransaction(contract: TestCustomErrors)
{.contract, errors:[ErrorWithArguments].}
let contract = contract.connect(provider.getSigner())
try:
await contract.revertsTransaction()
fail()
except ErrorWithArguments as error:
check error.arguments.one == 1.u256
check error.arguments.two == true
test "handles transaction submission errors":
proc revertsTransaction(contract: TestCustomErrors)
{.contract, errors:[ErrorWithArguments].}
# skip gas estimation
let overrides = TransactionOverrides(gasLimit: some 1000000.u256)
let contract = contract.connect(provider.getSigner())
try:
await contract.revertsTransaction(overrides = overrides)
fail()
except ErrorWithArguments as error:
check error.arguments.one == 1.u256
check error.arguments.two == true
test "handles transaction confirmation errors":
proc revertsTransaction(contract: TestCustomErrors): Confirmable
{.contract, errors:[ErrorWithArguments].}
# skip gas estimation
let overrides = TransactionOverrides(gasLimit: some 1000000.u256)
# ensure that transaction is not immediately checked by hardhat
discard await provider.send("evm_setAutomine", @[%false])
let contract = contract.connect(provider.getSigner())
try:
let future = contract.revertsTransaction(overrides = overrides).confirm(1)
await sleepAsync(100.millis) # wait for transaction to be submitted
discard await provider.send("evm_mine", @[]) # mine the transaction
discard await future # wait for confirmation
fail()
except ErrorWithArguments as error:
check error.arguments.one == 1.u256
check error.arguments.two == true
# re-enable auto mining
discard await provider.send("evm_setAutomine", @[%true])