Skip to content

Commit

Permalink
✅ Test: Add missing handlers test coverage (#810)
Browse files Browse the repository at this point in the history
## Description

_Concise description of proposed changes_

## Testing

Explain the quality checks that have been done on the code changes

## Additional Information

- [ ] I read the [contributing docs](../docs/contributing.md) (if this
is your first contribution)

Your ENS/address:



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Refactor**
	- Streamlined the contract call process for improved efficiency.

- **Tests**
	- Enhanced testing for error handling during contract calls.
	- Added tests for unexpected EVM behavior.

- **Bug Fixes**
- Corrected test suite descriptions and assertions for consistency and
accuracy.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Will Cory <[email protected]>
  • Loading branch information
roninjin10 and Will Cory authored Jan 11, 2024
1 parent 0efe3b0 commit 42f0775
Show file tree
Hide file tree
Showing 11 changed files with 608 additions and 54 deletions.
30 changes: 15 additions & 15 deletions tevm/docs/modules/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ Account JSON-RPC tevm procedure puts an account or contract into the tevm state

#### Defined in

vm/api/dist/index.d.ts:584
vm/api/dist/index.d.ts:587

___

Expand All @@ -217,7 +217,7 @@ JSON-RPC request for `tevm_account` method

#### Defined in

vm/api/dist/index.d.ts:512
vm/api/dist/index.d.ts:515

___

Expand All @@ -227,7 +227,7 @@ ___

#### Defined in

vm/api/dist/index.d.ts:569
vm/api/dist/index.d.ts:572

___

Expand Down Expand Up @@ -365,7 +365,7 @@ Call JSON-RPC procedure executes a call against the tevm EVM

#### Defined in

vm/api/dist/index.d.ts:589
vm/api/dist/index.d.ts:592

___

Expand All @@ -377,7 +377,7 @@ JSON-RPC request for `tevm_call`

#### Defined in

vm/api/dist/index.d.ts:517
vm/api/dist/index.d.ts:520

___

Expand All @@ -387,7 +387,7 @@ ___

#### Defined in

vm/api/dist/index.d.ts:571
vm/api/dist/index.d.ts:574

___

Expand Down Expand Up @@ -456,7 +456,7 @@ Since ContractJsonRpcProcedure is a quality of life wrapper around CallJsonRpcPr

#### Defined in

vm/api/dist/index.d.ts:596
vm/api/dist/index.d.ts:599

___

Expand All @@ -469,7 +469,7 @@ in favor of overloading tevm_call

#### Defined in

vm/api/dist/index.d.ts:523
vm/api/dist/index.d.ts:526

___

Expand All @@ -482,7 +482,7 @@ in favor of overloading tevm_call

#### Defined in

vm/api/dist/index.d.ts:577
vm/api/dist/index.d.ts:580

___

Expand Down Expand Up @@ -792,7 +792,7 @@ Helper type for creating JSON-RPC request types

#### Defined in

vm/api/dist/index.d.ts:502
vm/api/dist/index.d.ts:505

___

Expand All @@ -810,7 +810,7 @@ ___

#### Defined in

vm/api/dist/index.d.ts:552
vm/api/dist/index.d.ts:555

___

Expand Down Expand Up @@ -911,7 +911,7 @@ Procedure for handling script JSON-RPC requests

#### Defined in

vm/api/dist/index.d.ts:601
vm/api/dist/index.d.ts:604

___

Expand All @@ -923,7 +923,7 @@ The JSON-RPC request for the `tevm_script` method

#### Defined in

vm/api/dist/index.d.ts:544
vm/api/dist/index.d.ts:547

___

Expand All @@ -933,7 +933,7 @@ ___

#### Defined in

vm/api/dist/index.d.ts:579
vm/api/dist/index.d.ts:582

___

Expand All @@ -957,7 +957,7 @@ for each type of request

#### Defined in

vm/api/dist/index.d.ts:619
vm/api/dist/index.d.ts:622

___

Expand Down
8 changes: 4 additions & 4 deletions tevm/docs/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ ___

### ContractResult

Ƭ **ContractResult**\<`TAbi`, `TFunctionName`, `ErrorType`\>: [`CallResult`](index.md#callresult)\<`ErrorType`\> & \{ `data`: `DecodeFunctionResultReturnType`\<`TAbi`, `TFunctionName`\> }
Ƭ **ContractResult**\<`TAbi`, `TFunctionName`, `ErrorType`\>: `Omit`\<[`CallResult`](index.md#callresult), ``"errors"``\> & \{ `data`: `DecodeFunctionResultReturnType`\<`TAbi`, `TFunctionName`\> ; `errors?`: `never` } \| [`CallResult`](index.md#callresult)\<`ErrorType`\> & \{ `data?`: `never` }

#### Type parameters

Expand Down Expand Up @@ -276,7 +276,7 @@ ___

#### Defined in

vm/api/dist/index.d.ts:485
vm/api/dist/index.d.ts:488

___

Expand Down Expand Up @@ -321,7 +321,7 @@ A Tevm JSON-RPC request

#### Defined in

vm/api/dist/index.d.ts:550
vm/api/dist/index.d.ts:553

___

Expand Down Expand Up @@ -354,7 +354,7 @@ Generic and returns the correct response type for a given request

#### Defined in

vm/api/dist/index.d.ts:612
vm/api/dist/index.d.ts:615

## Functions

Expand Down
2 changes: 1 addition & 1 deletion vm/api/docs/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ ___

### ContractResult

Ƭ **ContractResult**\<`TAbi`, `TFunctionName`, `ErrorType`\>: [`CallResult`](modules.md#callresult)\<`ErrorType`\> & \{ `data`: `DecodeFunctionResultReturnType`\<`TAbi`, `TFunctionName`\> }
Ƭ **ContractResult**\<`TAbi`, `TFunctionName`, `ErrorType`\>: `Omit`\<[`CallResult`](modules.md#callresult), ``"errors"``\> & \{ `data`: `DecodeFunctionResultReturnType`\<`TAbi`, `TFunctionName`\> ; `errors?`: `never` } \| [`CallResult`](modules.md#callresult)\<`ErrorType`\> & \{ `data?`: `never` }

#### Type parameters

Expand Down
20 changes: 11 additions & 9 deletions vm/api/src/result/ContractResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ export type ContractResult<
TAbi extends Abi | readonly unknown[] = Abi,
TFunctionName extends ContractFunctionName<TAbi> = ContractFunctionName<TAbi>,
ErrorType = ContractError,
> = (Omit<CallResult, 'errors'> & {
errors: never,
/**
* The parsed data
*/
data: DecodeFunctionResultReturnType<TAbi, TFunctionName>
}) | (CallResult<ErrorType> & {
data: never
})
> =
| (Omit<CallResult, 'errors'> & {
errors?: never
/**
* The parsed data
*/
data: DecodeFunctionResultReturnType<TAbi, TFunctionName>
})
| (CallResult<ErrorType> & {
data?: never
})
4 changes: 1 addition & 3 deletions vm/procedures/src/handlers/callHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ export const callHandler = (evm) => async (params) => {
return { errors, executionGasUsed: 0n, rawData: '0x' }
}

const opts = callHandlerOpts(params)

try {
const evmResult = await evm.runCall(opts)
const evmResult = await evm.runCall(callHandlerOpts(params))
return callHandlerResult(evmResult)
} catch (e) {
return {
Expand Down
68 changes: 66 additions & 2 deletions vm/procedures/src/handlers/callHandler.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { accountHandler } from './accountHandler.js'
import { callHandler } from './callHandler.js'
import { EVM } from '@ethereumjs/evm'
import { EVM, EVMErrorMessage } from '@ethereumjs/evm'
import { Address } from '@ethereumjs/util'
import { describe, expect, it } from 'bun:test'
import { encodeFunctionData } from 'viem'
Expand Down Expand Up @@ -291,7 +291,7 @@ const ERC20_ABI = [
},
] as const

describe('contractHandler', () => {
describe('callHandler', () => {
it('should execute a contract call', async () => {
const evm = new EVM({})
// deploy contract
Expand Down Expand Up @@ -344,4 +344,68 @@ describe('contractHandler', () => {
(await evm.stateManager.getAccount(Address.fromString(to)))?.balance,
).toEqual(420n)
})

it('should handle errors returned during contract call', async () => {
const evm = new EVM({})
// deploy contract
expect(
(
await accountHandler(evm)({
address: ERC20_ADDRESS,
deployedBytecode: ERC20_BYTECODE,
})
).errors,
).toBeUndefined()
// test contract call that should fail from lack of owning any tokens
const caller = `0x${'23'.repeat(20)}` as const
expect(
await callHandler(evm)({
data: encodeFunctionData({
abi: ERC20_ABI,
functionName: 'transferFrom',
args: [caller, caller, 1n],
}),
to: ERC20_ADDRESS,
}),
).toEqual({
logs: [],
createdAddresses: new Set(),
errors: [
{
_tag: EVMErrorMessage.REVERT,
message: 'There was an error executing the evm',
name: EVMErrorMessage.REVERT,
},
],
executionGasUsed: 2754n,
gas: 16774461n,
rawData:
'0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000184461692f696e73756666696369656e742d62616c616e63650000000000000000',
selfdestruct: new Set(),
})
})

it('should handle the EVM unexpectedly throwing', async () => {
const evm = new EVM({})
evm.runCall = () => {
throw new Error('Unexpected error')
}
expect(
await callHandler(evm)({
data: '0x0',
to: ERC20_ADDRESS,
value: 420n,
}),
).toEqual({
errors: [
{
_tag: 'UnexpectedError',
message: 'Unexpected error',
name: 'UnexpectedError',
},
],
executionGasUsed: 0n,
rawData: '0x',
})
})
})
20 changes: 15 additions & 5 deletions vm/procedures/src/handlers/callHandlerResult.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { callHandlerResult } from './callHandlerResult.js'
import type { EVMResult } from '@ethereumjs/evm'
import type { EVMResult, Log } from '@ethereumjs/evm'
import { describe, expect, it } from 'bun:test'
import { getAddress, toHex } from 'viem'
import { bytesToHex, getAddress, toHex } from 'viem'

describe('callHandlerResult', () => {
const dummyAddress = `0x${'1'.repeat(40)}` as const

const mockLog: Log = [
new Uint8Array(20), // Address
[new Uint8Array(32), new Uint8Array(32)], // Topics (an array of two Uint8Array elements)
new Uint8Array(64), // Data
] as const
const dummyEVMResult = {
execResult: {
returnValue: Buffer.from('test'),
executionGasUsed: 21000n,
gasRefund: 1000n,
selfdestruct: new Set([dummyAddress]),
gas: 50000n,
logs: [],
logs: [mockLog],
blobGasUsed: 3000n,
createdAddresses: new Set([dummyAddress]),
},
Expand All @@ -26,7 +30,13 @@ describe('callHandlerResult', () => {
expect(result.gasRefund).toEqual(1000n)
expect(result.selfdestruct).toEqual(new Set([getAddress(dummyAddress)]))
expect(result.gas).toEqual(50000n)
expect(result.logs).toEqual([])
expect(result.logs).toEqual([
{
address: bytesToHex(mockLog[0]),
topics: mockLog[1].map((b) => bytesToHex(b)),
data: bytesToHex(mockLog[2]),
},
])
expect(result.blobGasUsed).toEqual(3000n)
expect(result.createdAddresses).toEqual(new Set([getAddress(dummyAddress)]))
})
Expand Down
Loading

1 comment on commit 42f0775

@vercel
Copy link

@vercel vercel bot commented on 42f0775 Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

evmts-docs – ./

evmts-docs-evmts.vercel.app
evmts.dev
evmts-docs-git-main-evmts.vercel.app

Please sign in to comment.