From 1ca90d0b3c498da466322cf9a41720884cfdafad Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Tue, 18 Apr 2023 17:28:28 +0200 Subject: [PATCH] Allow contract calls to override the block tag --- ethers/contract.nim | 35 +++++++++++++++++++++++------------ testmodule/testContracts.nim | 12 ++++++++++++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/ethers/contract.nim b/ethers/contract.nim index 100d316..72c27e5 100644 --- a/ethers/contract.nim +++ b/ethers/contract.nim @@ -16,13 +16,15 @@ type provider: Provider signer: ?Signer address: Address - TransactionOverrides* = object + TransactionOverrides* = ref object of RootObj nonce*: ?UInt256 chainId*: ?UInt256 gasPrice*: ?UInt256 maxFee*: ?UInt256 maxPriorityFee*: ?UInt256 gasLimit*: ?UInt256 + CallOverrides* = ref object of TransactionOverrides + blockTag*: ?BlockTag ContractError* = object of EthersError Confirmable* = ?TransactionResponse @@ -56,7 +58,7 @@ template raiseContractError(message: string) = proc createTransaction(contract: Contract, function: string, parameters: tuple, - overrides = TransactionOverrides.default): Transaction = + overrides = TransactionOverrides()): Transaction = let selector = selector(function, typeof parameters).toArray let data = @selector & AbiEncoder.encode(parameters) Transaction( @@ -78,27 +80,36 @@ proc decodeResponse(T: type, multiple: static bool, bytes: seq[byte]): T = else: return decodeResponse((T,), true, bytes)[0] +proc call(provider: Provider, + transaction: Transaction, + overrides: TransactionOverrides): Future[seq[byte]] = + if overrides of CallOverrides and + blockTag =? CallOverrides(overrides).blockTag: + provider.call(transaction, blockTag) + else: + provider.call(transaction) + proc call(contract: Contract, function: string, parameters: tuple, - blockTag = BlockTag.latest) {.async.} = - let transaction = createTransaction(contract, function, parameters) - discard await contract.provider.call(transaction, blockTag) + overrides = TransactionOverrides()) {.async.} = + let transaction = createTransaction(contract, function, parameters, overrides) + discard await contract.provider.call(transaction, overrides) proc call(contract: Contract, function: string, parameters: tuple, ReturnType: type, returnMultiple: static bool, - blockTag = BlockTag.latest): Future[ReturnType] {.async.} = - let transaction = createTransaction(contract, function, parameters) - let response = await contract.provider.call(transaction, blockTag) + overrides = TransactionOverrides()): Future[ReturnType] {.async.} = + let transaction = createTransaction(contract, function, parameters, overrides) + let response = await contract.provider.call(transaction, overrides) return decodeResponse(ReturnType, returnMultiple, response) proc send(contract: Contract, function: string, parameters: tuple, - overrides = TransactionOverrides.default): + overrides = TransactionOverrides()): Future[?TransactionResponse] {.async.} = if signer =? contract.signer: let transaction = createTransaction(contract, function, parameters, overrides) @@ -136,7 +147,7 @@ func addOverrides(procedure: var NimNode) = newIdentDefs( ident("overrides"), newEmptyNode(), - quote do: TransactionOverrides.default + quote do: TransactionOverrides() ) ) @@ -152,11 +163,11 @@ func addContractCall(procedure: var NimNode) = func call: NimNode = if returnType.kind == nnkEmpty: quote: - await call(`contract`, `function`, `parameters`) + await call(`contract`, `function`, `parameters`, overrides) else: quote: return await call( - `contract`, `function`, `parameters`, `returnType`, `returnMultiple`) + `contract`, `function`, `parameters`, `returnType`, `returnMultiple`, overrides) func send: NimNode = if returnType.kind == nnkEmpty: diff --git a/testmodule/testContracts.nim b/testmodule/testContracts.nim index 460d0ef..4282cdb 100644 --- a/testmodule/testContracts.nim +++ b/testmodule/testContracts.nim @@ -116,6 +116,18 @@ suite "Contracts": check signer.transactions[0].gasPrice == overrides.gasPrice check signer.transactions[0].gasLimit == overrides.gasLimit + test "can call functions for different block heights": + let block1 = await provider.getBlockNumber() + let signer = provider.getSigner(accounts[0]) + discard await token.connect(signer).mint(accounts[0], 100.u256) + let block2 = await provider.getBlockNumber() + + let beforeMint = CallOverrides(blockTag: some BlockTag.init(block1)) + let afterMint = CallOverrides(blockTag: some BlockTag.init(block2)) + + check (await token.balanceOf(accounts[0], beforeMint)) == 0 + check (await token.balanceOf(accounts[0], afterMint)) == 100 + test "receives events when subscribed": var transfers: seq[Transfer]