-
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## 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 ## Release Notes - **New Features** - Introduced the `anvil_deal` JSON-RPC request for handling ERC20 token transactions. - Added the `eth_createAccessList` JSON-RPC request to create access lists for Ethereum transactions. - Implemented a new `deal` method in the `TevmActionsApi` for ERC20 token distribution. - **Bug Fixes** - Enhanced error handling in transaction procedures to ensure robust responses. - **Tests** - Added unit tests for the new `anvil_deal` and `eth_createAccessList` procedures to validate functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Loading branch information
1 parent
1a03258
commit b99de65
Showing
26 changed files
with
468 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
"@tevm/memory-client": minor | ||
"@tevm/decorators": minor | ||
"@tevm/actions": minor | ||
--- | ||
|
||
Added eth_createAccessList and anvil_deal json-rpc requests | ||
Added MemoryClient.deal action |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { ERC20 } from '@tevm/contract' | ||
import { numberToHex } from '@tevm/utils' | ||
import { encodeFunctionData } from 'viem' | ||
import { setAccountHandler } from '../SetAccount/setAccountHandler.js' | ||
import { ethCreateAccessListProcedure } from '../eth/ethCreateAccessListProcedure.js' | ||
import { anvilSetStorageAtJsonRpcProcedure } from './anvilSetStorageAtProcedure.js' | ||
|
||
/** | ||
* Deals ERC20 tokens to an account by overriding the storage of balanceOf(account) | ||
* @param {import('@tevm/node').TevmNode} client | ||
* @returns {import('./AnvilHandler.js').AnvilDealHandler} | ||
*/ | ||
export const dealHandler = | ||
(client) => | ||
async ({ erc20, account, amount }) => { | ||
if (!erc20) { | ||
return setAccountHandler(client)({ | ||
address: account, | ||
balance: amount, | ||
}) | ||
} | ||
|
||
const value = numberToHex(amount, { size: 32 }) | ||
|
||
// Get storage slots accessed by balanceOf | ||
const accessListResponse = await ethCreateAccessListProcedure(client)({ | ||
method: 'eth_createAccessList', | ||
params: [ | ||
{ | ||
to: erc20, | ||
data: encodeFunctionData({ | ||
abi: ERC20.abi, | ||
functionName: 'balanceOf', | ||
args: [account], | ||
}), | ||
}, | ||
], | ||
id: 1, | ||
jsonrpc: '2.0', | ||
}) | ||
|
||
if (!accessListResponse.result?.accessList) { | ||
throw new Error('Failed to get access list') | ||
} | ||
|
||
// Try each storage slot until we find the right one | ||
for (const { address, storageKeys } of accessListResponse.result.accessList) { | ||
for (const slot of storageKeys) { | ||
await anvilSetStorageAtJsonRpcProcedure(client)({ | ||
method: 'anvil_setStorageAt', | ||
params: [address, slot, value], | ||
id: 1, | ||
jsonrpc: '2.0', | ||
}) | ||
} | ||
} | ||
|
||
return {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { hexToBigInt } from 'viem' | ||
import { dealHandler } from './anvilDealHandler.js' | ||
|
||
/** | ||
* JSON-RPC procedure for anvil_deal | ||
* Deals ERC20 tokens to an account by overriding the storage of balanceOf(account) | ||
* @param {import('@tevm/node').TevmNode} client | ||
* @returns {import('./AnvilProcedure.js').AnvilDealProcedure} | ||
* @example | ||
* ```typescript | ||
* const response = await client.request({ | ||
* method: 'anvil_deal', | ||
* params: [{ | ||
* erc20: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // Optional: USDC address | ||
* account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', | ||
* amount: 1000000n // 1 USDC (6 decimals) | ||
* }], | ||
* id: 1, | ||
* jsonrpc: '2.0' | ||
* }) | ||
* ``` | ||
*/ | ||
export const anvilDealJsonRpcProcedure = (client) => async (request) => { | ||
const [{ erc20, account, amount }] = request.params | ||
|
||
const result = await dealHandler(client)({ | ||
...(erc20 !== undefined ? { erc20 } : {}), | ||
account, | ||
amount: hexToBigInt(amount), | ||
}) | ||
|
||
if ('errors' in result && result.errors) { | ||
/** | ||
* @type {import('./AnvilJsonRpcResponse.js').AnvilDealJsonRpcResponse} | ||
*/ | ||
const out = { | ||
jsonrpc: request.jsonrpc, | ||
...(request.id !== undefined ? { id: request.id } : {}), | ||
method: 'anvil_deal', | ||
error: { | ||
// @ts-expect-error being lazy here | ||
code: (result.errors[0]?.code ?? -32000).toString(), | ||
message: result.errors[0]?.message ?? result.errors[0]?.name ?? 'An unknown error occured', | ||
}, | ||
} | ||
return out | ||
} | ||
|
||
return { | ||
jsonrpc: request.jsonrpc, | ||
...(request.id !== undefined ? { id: request.id } : {}), | ||
method: 'anvil_deal', | ||
result: {}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { createAddress } from '@tevm/address' | ||
import { createTevmNode } from '@tevm/node' | ||
import { TestERC20 } from '@tevm/test-utils' | ||
import { describe, expect, it } from 'vitest' | ||
import { setAccountHandler } from '../SetAccount/setAccountHandler.js' | ||
import { anvilDealJsonRpcProcedure } from './anvilDealProcedure.js' | ||
|
||
describe('anvilDealJsonRpcProcedure', () => { | ||
it('should deal ERC20 tokens', async () => { | ||
const client = createTevmNode() | ||
const erc20 = TestERC20.withAddress(createAddress('0x66a44').toString()) | ||
|
||
// Deploy contract | ||
await setAccountHandler(client)({ | ||
address: erc20.address, | ||
deployedBytecode: erc20.deployedBytecode, | ||
}) | ||
|
||
const result = await anvilDealJsonRpcProcedure(client)({ | ||
method: 'anvil_deal', | ||
params: [ | ||
{ | ||
erc20: erc20.address, | ||
account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', | ||
amount: '0xf4240', // 1M (6 decimals) | ||
}, | ||
], | ||
id: 1, | ||
jsonrpc: '2.0', | ||
}) | ||
|
||
expect(result).toEqual({ | ||
jsonrpc: '2.0', | ||
id: 1, | ||
method: 'anvil_deal', | ||
result: {}, | ||
}) | ||
}) | ||
|
||
it('should deal native tokens when no erc20 address provided', async () => { | ||
const client = createTevmNode() | ||
|
||
const result = await anvilDealJsonRpcProcedure(client)({ | ||
method: 'anvil_deal', | ||
params: [ | ||
{ | ||
account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', | ||
amount: '0xde0b6b3a7640000', // 1 ETH | ||
}, | ||
], | ||
id: 1, | ||
jsonrpc: '2.0', | ||
}) | ||
|
||
expect(result).toEqual({ | ||
jsonrpc: '2.0', | ||
id: 1, | ||
method: 'anvil_deal', | ||
result: {}, | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.