-
-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Feat: Add anvil_deal #1492
✨ Feat: Add anvil_deal #1492
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Skipped Deployment
|
🦋 Changeset detectedLatest commit: 0522e0e The changes in this PR will be included in the next version bump. This PR includes changesets to release 10 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughThe changes in this pull request introduce new JSON-RPC functionalities, specifically the Changes
Possibly related PRs
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
This stack of pull requests is managed by Graphite. Learn more about stacking. Join @roninjin10 and the rest of your teammates on Graphite |
25336ce
to
0522e0e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 15
🧹 Outside diff range and nitpick comments (24)
packages/actions/src/anvil/AnvilResult.ts (1)
34-37
: Add JSDoc documentation for the new type.The type definition looks good, but could benefit from JSDoc documentation explaining its purpose and usage.
Consider adding documentation like this:
// anvil_deal +/** + * Result type for the anvil_deal JSON-RPC method. + * @property {Error[]} [errors] - Optional array of errors that occurred during the deal operation + */ export type AnvilDealResult = { errors?: Error[] }packages/actions/src/eth/ethSendTransactionProcedure.js (3)
Line range hint
15-20
: Consider handling zero values explicitly.The current implementation might incorrectly exclude zero values since
value && {...}
would evaluate0
as falsy. Consider using explicit existence checks.Here's a more robust implementation:
- ...(request.params[0].from ? { from: request.params[0].from } : {}), - ...(request.params[0].data ? { data: request.params[0].data } : {}), - ...(request.params[0].to ? { to: request.params[0].to } : {}), - ...(request.params[0].gas ? { gas: hexToBigInt(request.params[0].gas) } : {}), - ...(request.params[0].gasPrice ? { gasPrice: hexToBigInt(request.params[0].gasPrice) } : {}), - ...(request.params[0].value ? { value: hexToBigInt(request.params[0].value) } : {}), + ...('from' in request.params[0] ? { from: request.params[0].from } : {}), + ...('data' in request.params[0] ? { data: request.params[0].data } : {}), + ...('to' in request.params[0] ? { to: request.params[0].to } : {}), + ...('gas' in request.params[0] ? { gas: hexToBigInt(request.params[0].gas) } : {}), + ...('gasPrice' in request.params[0] ? { gasPrice: hexToBigInt(request.params[0].gasPrice) } : {}), + ...('value' in request.params[0] ? { value: hexToBigInt(request.params[0].value) } : {}),
Line range hint
15-20
: Consider adding gas estimation fallback.When
gas
is not provided, consider adding automatic gas estimation to improve user experience.This could be implemented by:
- Checking if gas is missing
- Using eth_estimateGas RPC call to calculate it
- Falling back to a safe default if estimation fails
Would you like me to provide a detailed implementation for this enhancement?
Based on the code inspection, I can now provide a final response:
Parameter validation is needed for transaction fields
The current implementation lacks essential validation for Ethereum transaction parameters. While the code uses
hexToBigInt
for numeric conversions, there's no validation for:
- Ethereum address format for
to
andfrom
fields- Hex string format validation before conversion
- Value range checks for numeric fields
Key findings from the codebase:
- The
BaseCallParams
type defines the expected types but there's no runtime validation- The
ethSendTransactionHandler
processes the transaction without validating inputs- No evidence of address or hex format validation in the current flow
🔗 Analysis chain
Line range hint
15-20
: Consider adding parameter validation.The current implementation might benefit from additional validation:
- Hex string format validation before conversion
- Address format validation for
to
andfrom
fields- Value range checks for
gas
,gasPrice
, andvalue
Let's check if there's existing validation elsewhere:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for validation related to eth_sendTransaction rg -A 5 "eth_sendTransaction.*valid" # Check for potential error handling ast-grep --pattern 'try { $$$ hexToBigInt($_) $$$ } catch'Length of output: 105
Script:
#!/bin/bash # Let's check for any validation in the ethSendTransactionProcedure file rg -A 10 "validate|check|verify" packages/actions/src/eth/ethSendTransactionProcedure.js # Look for any validation utilities that might be imported rg "import.*validate|check|verify" packages/actions/src/eth/ethSendTransactionProcedure.js # Check implementation of hexToBigInt for error handling rg -l "hexToBigInt" packages/actions/src/ fd hexToBigInt.js packages/actions/src/ -x cat {} # Search for any ethereum address validation utilities rg -l "isAddress|validateAddress|checkAddress" packages/actions/src/Length of output: 1423
Script:
#!/bin/bash # Let's check the implementation of hexToBigInt in the utils cat packages/actions/src/utils/parseBlockTag.js # Check if there's any error handling or validation in the ethSendTransactionProcedure cat packages/actions/src/eth/ethSendTransactionProcedure.js # Look for any ethereum-specific validation utilities in the project rg -l "0x[a-fA-F0-9]|isHex|isValidHex" packages/actions/src/ fd validator.js packages/actions/src/ -x cat {}Length of output: 10033
Script:
#!/bin/bash # Let's check if there's validation in the imported @tevm/utils package's hexToBigInt cat packages/actions/src/eth/ethSendTransactionHandler.js # Check for any validation in BaseCallParams since it might contain common validation cat packages/actions/src/BaseCall/validateBaseCallParams.spec.ts cat packages/actions/src/BaseCall/BaseCallParams.ts # Look for any Ethereum address validation rg -A 5 "validateAddress|isValidAddress|checkAddress" packages/actions/src/Length of output: 16725
packages/actions/src/anvil/anvilDealProcedure.spec.ts (1)
8-62
: Consider adding test cases for edge scenarios.The current test suite covers the happy path for both ERC20 and native tokens. Consider adding tests for:
- Invalid addresses
- Zero amounts
- Invalid ERC20 contracts (non-compliant or non-existent)
- Overflow amounts
- Reentrant calls
Would you like me to help generate these additional test cases?
packages/actions/src/eth/ethCreateAccessListProcedure.spec.ts (1)
9-9
: Document the significance of the magic number.Consider adding a comment explaining why the specific value
420420
was chosen for the contract address, or consider using a more meaningful constant.+// Using an arbitrary but consistent address for testing const erc20 = TestERC20.withAddress(createAddress(420420).toString())
packages/actions/src/eth/ethCreateAccessListProcedure.js (2)
1-8
: Consider enhancing documentation with examplesThe documentation clearly describes the purpose, but adding an @example section would help developers understand the expected input and output format.
Add example usage:
/** * Creates an access list for a transaction. * Returns list of addresses and storage keys that the transaction plans to access. * @param {import('@tevm/node').TevmNode} client * @returns {import('./EthProcedure.js').EthCreateAccessListJsonRpcProcedure} + * @example + * const accessList = await ethCreateAccessListProcedure(client)({ + * jsonrpc: '2.0', + * method: 'eth_createAccessList', + * params: [{ + * from: '0x...', + * to: '0x...', + * data: '0x...' + * }] + * }) */
12-28
: Consider explicit blockTag validation and defaultThe blockTag parameter is passed through without validation or default value. Consider adding explicit handling for different block tag formats (latest, pending, earliest, or block number).
Consider adding validation:
const response = await callProcedure(client)({ ...(req.id !== undefined ? { id: req.id } : {}), jsonrpc: req.jsonrpc, method: 'tevm_call', params: [ { ...(gasPrice !== undefined ? { gasPrice } : {}), ...(data !== undefined ? { data } : {}), ...(gas !== undefined ? { gas } : {}), ...(value !== undefined ? { value } : {}), ...(to !== undefined ? { to } : {}), ...(from !== undefined ? { from } : {}), - ...(blockTag !== undefined ? { blockTag } : {}), + blockTag: blockTag ?? 'latest', // Provide default createAccessList: true, }, ], })packages/decorators/src/actions/tevmActions.js (1)
85-93
: Consider enhancing JSDoc documentationWhile the implementation is correct and follows the established pattern, consider adding a description to the JSDoc comment explaining the purpose of the deal action, similar to other handlers in the codebase.
/** * @internal + * Creates a deal action that allows setting token balances + * @see dealHandler * @returns {import('@tevm/node').Extension<Pick<import('./TevmActionsApi.js').TevmActionsApi, 'deal'>>} */packages/actions/src/anvil/AnvilHandler.ts (1)
69-70
: LGTM! The new AnvilDealHandler type follows the established pattern.The type definition is consistent with other handlers in the file and properly typed with the corresponding params and result types.
Consider adding a JSDoc comment to document the purpose and usage of this handler, similar to how other handlers have inline comments. Example:
// anvil_deal - Handler for setting ERC20 token balances export type AnvilDealHandler = (params: AnvilDealParams) => Promise<AnvilDealResult>packages/actions/src/tevm-request-handler/TevmJsonRpcRequestHandler.ts (1)
82-100
: Documentation looks good, but example could be more comprehensive.The documentation follows the established pattern and clearly describes the purpose of
eth_createAccessList
. However, the example could be enhanced to be more educational.Consider expanding the example to include:
- More realistic parameter values
- Common use cases
- Example response structure
const response = await tevm.request({ method: 'eth_createAccessList', params: [{ - to: '0x...', - data: '0x...' + from: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + to: '0x1234567890123456789012345678901234567890', + data: '0xa9059cbb000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef0000000000000000000000000000000000000000000000056bc75e2d63100000', + gas: '0x7530', + gasPrice: '0x1e8480', + value: '0x0' }], id: 1, jsonrpc: '2.0' }) +// Example response: +// { +// accessList: [{ +// address: '0x1234567890123456789012345678901234567890', +// storageKeys: [ +// '0x0000000000000000000000000000000000000000000000000000000000000001' +// ] +// }], +// gasUsed: '0x7530' +// }packages/actions/src/anvil/AnvilParams.ts (2)
Line range hint
1-3
: Address the TODO comment about JSDoc documentation.The comment indicates that JSDoc documentation needs to be updated. Consider reviewing and updating the documentation for all type definitions to ensure accuracy and completeness.
167-174
: Consider adding validation constraints and clarifying native token behavior.The type definition looks good overall, but consider the following improvements:
- Add documentation about native token behavior when
erc20
is undefined- Consider adding a minimum amount constraint or documentation about valid amount ranges
- Add an example usage in the JSDoc comment
Here's a suggested improvement with enhanced documentation:
export type AnvilDealParams = { + /** + * The address of the ERC20 token to deal. + * If undefined, deals native tokens instead of ERC20 + */ erc20?: Address + /** + * The owner of the dealt tokens. + * This address will receive the specified amount of tokens + */ account: Address + /** + * The amount of tokens to deal. + * For ERC20 tokens, this is in the token's smallest unit (e.g., wei for ETH) + * Must be a non-negative value + */ amount: bigint }packages/actions/src/anvil/AnvilJsonRpcResponse.ts (1)
148-152
: Consider enhancing JSDoc documentationThe type definition is well-structured and follows the established pattern. Consider enhancing the JSDoc comment to include:
- Purpose of the
anvil_deal
procedure- Expected response format
- Potential error scenarios
Example:
/** * JSON-RPC response for `anvil_deal` procedure * Represents the response when setting an account's balance for testing purposes * @see AnvilDealResult for the success response format * @see AnvilError for possible error cases */packages/actions/src/anvil/AnvilJsonRpcRequest.ts (2)
115-119
: Consider enhancing the JSDoc documentationWhile the type definition is correct, consider enhancing the JSDoc comment to match the documentation level of other request types in the file. Include details about the purpose of the
anvil_deal
method and its parameters.Example enhancement:
/** * JSON-RPC request for `anvil_deal` method + * Allows setting up token balances for testing purposes + * @see AnvilDealParams for parameter details */
Missing implementation for anvil_deal handler
The type definitions for the
anvil_deal
feature are complete:
AnvilDealJsonRpcRequest
andAnvilDealJsonRpcResponse
types are definedAnvilDealParams
andAnvilDealResult
types existAnvilDealProcedure
andAnvilDealHandler
types are presentHowever, the actual implementation of the handler is missing. The codebase needs:
- Implementation of the
deal
handler function- Registration of the handler in the Anvil handler map
🔗 Analysis chain
Line range hint
115-136
: Verify complete implementation of anvil_deal featureLet's ensure all necessary companion types and procedures are in place for the
anvil_deal
functionality.
Let me gather more information about the
AnvilDealResult
type and check the actual implementation of the handler.
Let me check one final thing - the actual implementation of the handler in a different pattern since the first attempt didn't find it.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check for related implementations and types echo "Checking for AnvilDealParams definition..." rg -p "export.*AnvilDealParams.*=" packages/actions/src/anvil/ echo "Checking for anvil_deal procedure implementation..." rg -p "export.*AnvilDealProcedure" packages/actions/src/anvil/ echo "Checking for response type definition..." rg -p "export.*AnvilDealJsonRpcResponse" packages/actions/src/anvil/Length of output: 1188
Script:
#!/bin/bash # Check for AnvilDealResult and actual implementation echo "Checking for AnvilDealResult definition..." rg -p "export.*AnvilDealResult.*=" packages/actions/src/anvil/ echo "Checking for actual handler implementation..." ast-grep --pattern 'export const deal: AnvilDealHandler = async'Length of output: 404
Script:
#!/bin/bash # Check for deal implementation with broader pattern echo "Checking for deal implementation..." rg -p "deal.*=.*async.*AnvilDealParams" packages/actions/src/anvil/ echo "Checking handler registration..." rg -p "deal.*:.*AnvilDealHandler" packages/actions/src/anvil/Length of output: 289
packages/actions/src/anvil/AnvilProcedure.ts (1)
125-129
: Consider enhancing the JSDoc documentationWhile the type definition is correct, the JSDoc comment could be more descriptive about the purpose and behavior of the
anvil_deal
operation. Consider adding details about:
- What the procedure does
- Expected parameters
- Potential use cases
Example enhancement:
/** * JSON-RPC procedure for `anvil_deal` * Sets the balance of an account to a specific amount. * Useful for testing scenarios that require specific account balances. * @see AnvilDealJsonRpcRequest for parameter details */packages/actions/src/eth/EthJsonRpcResponse.ts (1)
327-341
: LGTM! Consider enhancing the documentation.The new
EthCreateAccessListJsonRpcResponse
type is well-structured and follows the established patterns. The type definition is correct and properly uses theAddress
andHex
types from@tevm/utils
.Consider enhancing the JSDoc comment to include:
- Purpose of the access list
- Description of the response fields
- Example usage
/** * JSON-RPC response for `eth_createAccessList` procedure + * + * Returns an access list and gas used for the transaction. + * This can be used to include in the `accessList` field of a transaction + * to avoid dynamic gas costs for state access during execution. + * + * @property accessList - List of addresses and storage keys that the transaction plans to access + * @property accessList[].address - The address of the contract to access + * @property accessList[].storageKeys - Array of storage keys to access + * @property gasUsed - The amount of gas used for this operation */packages/actions/src/eth/EthProcedure.ts (1)
212-215
: Consider adding detailed JSDoc documentationWhile the procedure follows the established pattern, consider adding a detailed JSDoc comment explaining the purpose and behavior of the
eth_createAccessList
procedure, similar to other procedures in the codebase.Example:
/** * JSON-RPC procedure for eth_createAccessList * Creates an access list for a transaction. * @see https://eips.ethereum.org/EIPS/eip-2930 */ export type EthCreateAccessListJsonRpcProcedure = ( request: EthCreateAccessListJsonRpcRequest, ) => Promise<EthCreateAccessListJsonRpcResponse>packages/memory-client/src/test/requests.spec.ts (2)
243-263
: Test case needs additional assertions and error scenarios.While the basic happy path is covered, consider enhancing the test coverage:
- Add error scenarios:
- Invalid
from
address- Invalid
to
address- Invalid contract data
- Add assertions for the complete response object structure
- Verify the gas estimation is reasonable for the operation
Here's a suggested enhancement:
it('should execute eth_createAccessList request', async () => { const tevm = createMemoryClient() + // Happy path const req = { method: 'eth_createAccessList', params: [ { from: '0x1f420000000000000000000000000000000000ff', to: contractAddress, data: encodeFunctionData(ERC20.read.balanceOf('0xf0d4c12a5768d806021f80a262b4d39d26c58b8d')), }, ], id: 1, jsonrpc: '2.0', } // @ts-expect-error todo doesn't exist in viem yet https://github.com/wevm/viem/discussions/1060 const res = await tevm.request(req) expect(res).toMatchObject({ accessList: [], gasUsed: '0x53b8', + error: undefined, }) + + // Error scenario - Invalid to address + const invalidReq = { + ...req, + params: [{ + ...req.params[0], + to: '0xinvalid' + }] + } + // @ts-expect-error + const invalidRes = await tevm.request(invalidReq) + expect(invalidRes.error).toBeDefined() })
242-243
: Maintain consistent test organization.Consider grouping related test cases together. Since this test involves ERC20 contract interaction, it could be grouped with other ERC20-related tests.
Consider reorganizing the tests using
describe
blocks:+ describe('ERC20 operations', () => { + // Move existing ERC20-related tests here it('should execute eth_createAccessList request', async () => { // ... existing test case }) + })packages/actions/src/eth/EthJsonRpcRequest.ts (2)
296-303
: Enhance documentation for eth_createAccessList.The type definition looks correct, but the documentation could be more descriptive about the purpose and usage of this RPC method.
Consider expanding the documentation to explain:
- The purpose of access lists
- When to use this method
- What the response contains
Line range hint
305-345
: Remove duplicate EthAccountsJsonRpcRequest from union type.There's a duplicate entry for
EthAccountsJsonRpcRequest
in theEthJsonRpcRequest
union type.Apply this fix:
export type EthJsonRpcRequest = | EthAccountsJsonRpcRequest - | EthAccountsJsonRpcRequest | EthBlockNumberJsonRpcRequest
packages/actions/src/anvil/anvilDealHandler.js (1)
25-41
: Consider a more reliable method to identify balance storage slotsUsing the access list from
eth_createAccessList
might not reliably identify the exact storage slots for thebalanceOf
mapping. Contracts may have different storage layouts due to inheritance patterns or storage optimization techniques.Consider retrieving the contract's storage layout via Solidity metadata or using EIPs like EIP-717 for standardized storage layouts. Alternatively, if interacting with standard ERC20 contracts, you might assume that the balance mapping is at slot
0
and calculate the storage slot using the account address:import { keccak256, toHex } from 'viem' // Compute the storage slot for balances mapping const slot = keccak256( encodeAbiParameters( [{ type: 'address' }, { type: 'uint256' }], [account, '0'] // '0' is the slot number for the balances mapping ) )This method provides a deterministic way to find the balance storage slot for standard ERC20 tokens.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (26)
.changeset/little-coats-float.md
(1 hunks)packages/actions/src/anvil/AnvilHandler.ts
(3 hunks)packages/actions/src/anvil/AnvilJsonRpcRequest.ts
(3 hunks)packages/actions/src/anvil/AnvilJsonRpcResponse.ts
(2 hunks)packages/actions/src/anvil/AnvilParams.ts
(1 hunks)packages/actions/src/anvil/AnvilProcedure.ts
(3 hunks)packages/actions/src/anvil/AnvilResult.ts
(1 hunks)packages/actions/src/anvil/anvilDealHandler.js
(1 hunks)packages/actions/src/anvil/anvilDealProcedure.js
(1 hunks)packages/actions/src/anvil/anvilDealProcedure.spec.ts
(1 hunks)packages/actions/src/anvil/index.ts
(1 hunks)packages/actions/src/createHandlers.js
(4 hunks)packages/actions/src/eth/EthJsonRpcRequest.ts
(3 hunks)packages/actions/src/eth/EthJsonRpcResponse.ts
(1 hunks)packages/actions/src/eth/EthProcedure.ts
(3 hunks)packages/actions/src/eth/ethCreateAccessListProcedure.js
(1 hunks)packages/actions/src/eth/ethCreateAccessListProcedure.spec.ts
(1 hunks)packages/actions/src/eth/ethSendTransactionProcedure.js
(1 hunks)packages/actions/src/eth/index.ts
(1 hunks)packages/actions/src/tevm-request-handler/AnvilRequestType.ts
(2 hunks)packages/actions/src/tevm-request-handler/AnvilReturnType.ts
(2 hunks)packages/actions/src/tevm-request-handler/EthReturnType.ts
(2 hunks)packages/actions/src/tevm-request-handler/TevmJsonRpcRequestHandler.ts
(1 hunks)packages/decorators/src/actions/TevmActionsApi.ts
(2 hunks)packages/decorators/src/actions/tevmActions.js
(3 hunks)packages/memory-client/src/test/requests.spec.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/actions/src/anvil/index.ts
🔇 Additional comments (41)
.changeset/little-coats-float.md (1)
1-8
: LGTM! Version bumps are appropriate for the new features.
The changeset correctly documents minor version bumps for all affected packages and provides a clear description of the new features.
Let's verify if all affected packages are included in the version bumps:
✅ Verification successful
The previous results showed the new RPC methods are implemented in @tevm/actions, but we need to verify the changes in memory-client and decorators packages to ensure the version bumps are justified.
The previous results show some references in the decorators package that we need to investigate further, and we need to verify the actual implementation details in memory-client since LICENSE matches aren't relevant.
Version bumps are correctly specified for all affected packages
The verification confirms that all three packages with version bumps are indeed affected by the new features:
- @tevm/actions: Contains the core implementation of eth_createAccessList and anvil_deal handlers
- @tevm/memory-client: Integrates the new RPC methods (verified in TevmActions.ts and tests)
- @tevm/decorators: Provides the deal action API and decorators (verified in TevmActionsApi.ts and tevmActions.js)
The minor version bumps are appropriate as these are new feature additions.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for potential missing package bumps by searching for new RPC methods and actions
# Test 1: Search for new RPC method implementations
# Expect: References only in bumped packages
rg -l "eth_createAccessList|anvil_deal"
# Test 2: Search for new action implementations
# Expect: References only in bumped packages
rg -l "MemoryClient\.deal"
Length of output: 1045
Script:
#!/bin/bash
# Let's search for deal-related implementations in a more comprehensive way
# since the exact "MemoryClient.deal" pattern didn't yield results
# Search for deal method/function definitions
ast-grep --pattern 'deal($$$) { $$$ }'
# Search for deal-related code with context
rg -A 3 '\bdeal\b' packages/memory-client/
# Check if decorators package is actually affected
rg -l '\bdeal\b' packages/decorators/
Length of output: 647
Script:
#!/bin/bash
# Let's check the actual implementation details in decorators package
rg -A 5 '\bdeal\b' packages/decorators/src/actions/
# Check memory-client implementation details
rg -l 'anvil_deal|createAccessList' packages/memory-client/src/
# Look for any deal-related type definitions or interfaces
ast-grep --pattern 'interface $_ { $$$ deal $$$ }'
Length of output: 1682
packages/actions/src/anvil/AnvilResult.ts (1)
34-37
: Verify the consistent usage of AnvilDealResult.
Let's verify that this type is properly integrated with related components.
✅ Verification successful
Based on the results, I can generate the final response as we have comprehensive information about the usage of AnvilDealResult
across the codebase.
AnvilDealResult
type is properly integrated across the codebase
The type is consistently used in all relevant components:
- Handler implementation (
AnvilHandler.ts
) - JSON-RPC request/response types (
AnvilJsonRpcRequest.ts
,AnvilJsonRpcResponse.ts
) - Request/Response type mappings (
AnvilRequestType.ts
,AnvilReturnType.ts
) - Test files (
anvilDealProcedure.spec.ts
)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check the usage of AnvilDealResult type across the codebase
# Expected: Should find references in handler and JSON-RPC related files
echo "Checking for AnvilDealResult usage:"
rg "AnvilDealResult" --type ts
echo -e "\nChecking for anvil_deal method implementations:"
rg "anvil_deal" --type ts
Length of output: 2157
packages/actions/src/eth/ethSendTransactionProcedure.js (1)
Line range hint 15-20
: LGTM: Improved transaction parameter handling.
The conditional spreading of parameters is a good approach to prevent undefined values in the transaction object.
packages/actions/src/tevm-request-handler/AnvilRequestType.ts (2)
2-2
: LGTM: Import statement follows existing conventions
The new import is correctly placed and follows the established pattern for Anvil request types.
35-35
: LGTM: Verify handler implementation
The new mapping is correctly added to the AnvilRequestType
. Let's verify the corresponding handler implementation exists.
✅ Verification successful
Handler implementation is complete and well-integrated
The verification shows the anvil_deal
handler is properly implemented:
- Type definition in
packages/actions/src/anvil/AnvilHandler.ts
- Handler implementation in
packages/actions/src/anvil/anvilDealHandler.js
- Test coverage in
packages/actions/src/anvil/anvilDealProcedure.spec.ts
- Integration in the API surface via
TevmActionsApi.ts
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the handler implementation for anvil_deal exists
# Expected: Find the handler implementation in the codebase
# Search for AnvilDealHandler type definition
echo "Searching for handler type definition..."
ast-grep --pattern 'type AnvilDealHandler = $_'
# Search for anvil_deal handler implementation
echo "Searching for handler implementation..."
rg -l 'anvil_deal.*handler'
Length of output: 390
Script:
#!/bin/bash
# Let's search for the actual implementation of anvil_deal handler
# First, let's look for files containing 'anvil_deal'
echo "Files containing anvil_deal:"
rg -l "anvil_deal"
# Then, let's look for the actual handler implementation with more context
echo -e "\nHandler implementation context:"
rg -A 5 "anvil_deal.*handler|createAnvilDeal|AnvilDealHandler"
# Let's also check if there's a test file for this handler
echo -e "\nTest files:"
fd "deal.*test|deal.*spec"
Length of output: 1958
packages/actions/src/tevm-request-handler/AnvilReturnType.ts (1)
2-2
: LGTM! Clean implementation of the anvil_deal type mapping.
The changes correctly implement the type system for the new anvil_deal
JSON-RPC method, following the established patterns in the codebase. The import is properly organized, and the type mapping maintains consistency with other anvil methods.
Also applies to: 38-38
packages/actions/src/anvil/anvilDealProcedure.spec.ts (2)
1-7
: LGTM! Imports are well-organized and necessary.
All imports are being utilized and follow a logical organization pattern.
9-38
: 🛠️ Refactor suggestion
Enhance test coverage and documentation for ERC20 dealing.
The test case could be improved in several ways:
- Add balance verification after dealing tokens
- Document the hexadecimal amounts clearly
- Verify successful contract deployment
- Consider a more meaningful response structure
Consider refactoring the test to include these improvements:
it('should deal ERC20 tokens', async () => {
const client = createTevmNode()
const erc20 = TestERC20.withAddress(createAddress('0x66a44').toString())
+ const account = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
+ const amount = '0xf4240' // 1,000,000 (1M) tokens with 6 decimals
// Deploy contract
- await setAccountHandler(client)({
+ const deployResult = await setAccountHandler(client)({
address: erc20.address,
deployedBytecode: erc20.deployedBytecode,
})
+ expect(deployResult.deployed).toBe(true)
const result = await anvilDealJsonRpcProcedure(client)({
method: 'anvil_deal',
params: [
{
erc20: erc20.address,
- account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
- amount: '0xf4240', // 1M (6 decimals)
+ account,
+ amount,
},
],
id: 1,
jsonrpc: '2.0',
})
+ // Verify token balance
+ const balance = await client.contract({
+ address: erc20.address,
+ abi: erc20.abi,
+ }).read.balanceOf([account])
+ expect(balance.toString()).toBe(amount)
expect(result).toEqual({
jsonrpc: '2.0',
id: 1,
method: 'anvil_deal',
- result: {},
+ result: {
+ success: true,
+ balance: amount,
+ },
})
})
packages/actions/src/eth/ethCreateAccessListProcedure.spec.ts (1)
1-60
: Verify JSON-RPC interface integration.
The test covers the procedure implementation well, but consider adding integration tests to verify:
- The procedure is correctly registered with the JSON-RPC interface
- The method name 'eth_createAccessList' is properly mapped
- The response format adheres to the JSON-RPC spec
packages/actions/src/eth/ethCreateAccessListProcedure.js (3)
30-41
: LGTM! Error handling follows JSON-RPC spec
The error handling is well-structured and follows the JSON-RPC 2.0 specification. Good use of TypeScript type assertions for the response object.
49-58
: LGTM! Response construction is well-structured
The response format correctly follows the JSON-RPC 2.0 specification and includes appropriate fallback for gasUsed.
9-11
: Verify parameter validation
The code extracts transaction parameters but doesn't validate required fields. Some parameters might be required according to the Ethereum JSON-RPC spec.
Let's check the spec and other implementations:
packages/actions/src/eth/index.ts (1)
54-54
: LGTM! The new export follows established patterns.
The addition of ethCreateAccessListProcedure
export maintains consistency with existing exports in terms of naming convention, file extension, and alphabetical ordering.
Let's verify the existence of the exported file:
✅ Verification successful
The exported file exists and follows the established patterns ✅
The verification confirms that ethCreateAccessListProcedure.js
exists at the expected location in packages/actions/src/eth/
, making this a valid export statement.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that the exported file exists
# Expected: File should exist in the same directory
fd --type f "ethCreateAccessListProcedure.js" packages/actions/src/eth/
Length of output: 128
packages/decorators/src/actions/tevmActions.js (3)
4-4
: LGTM: Clean import addition
The dealHandler
import is properly integrated into the existing import structure.
108-108
: LGTM: Clean integration of dealAction
The dealAction is properly integrated into the tevmActions chain.
4-4
: Verify related components for the deal functionality
Let's ensure all required components for the deal functionality are properly set up.
Also applies to: 85-93, 108-108
✅ Verification successful
Let me verify the implementation details of the dealHandler to ensure it's properly set up.
All deal functionality components are properly integrated
The verification confirms that all required components are in place and properly connected:
- The
dealHandler
is implemented inpackages/actions/src/anvil/anvilDealHandler.js
with proper parameter handling - The handler is correctly imported and used in
anvilDealProcedure.js
TevmActionsApi
interface includes the deal method typeAnvilDealParams
type is properly defined with all required fields- JSON-RPC request type for
anvil_deal
is properly set up
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the existence and setup of related deal components
# Check if dealHandler is properly exported from @tevm/actions
echo "Checking dealHandler export..."
rg -l "export.*dealHandler" -g "packages/actions/**/*"
# Check if TevmActionsApi includes deal method type
echo "Checking TevmActionsApi interface..."
rg "deal.*:.*" -g "packages/decorators/src/actions/TevmActionsApi.ts"
# Check for anvil_deal JSON-RPC related files
echo "Checking anvil_deal JSON-RPC components..."
fd -g "**/Anvil*Request.ts" -x rg "anvil_deal" {}
Length of output: 709
Script:
#!/bin/bash
# Check the implementation of dealHandler
echo "Checking dealHandler implementation..."
rg -A 10 "export.*dealHandler" packages/actions/src/anvil/anvilDealHandler.js
# Check if the handler is properly imported and used
echo "Checking handler usage..."
rg "import.*dealHandler"
# Check for AnvilDealParams type definition
echo "Checking AnvilDealParams type..."
rg -A 5 "type AnvilDealParams"
Length of output: 1143
packages/actions/src/anvil/AnvilHandler.ts (1)
2-2
: LGTM! New type imports are properly organized.
The imports are correctly placed within their respective import groups and follow the established pattern.
Also applies to: 18-18
packages/actions/src/tevm-request-handler/TevmJsonRpcRequestHandler.ts (1)
81-100
: Verify the referenced types exist.
The documentation references EthCreateAccessListJsonRpcRequest
and EthCreateAccessListJsonRpcResponse
types.
Let's verify these types are properly defined:
✅ Verification successful
Both types are properly defined and used in the codebase
The search results confirm that both types are well-defined:
EthCreateAccessListJsonRpcRequest
is defined inpackages/actions/src/eth/EthJsonRpcRequest.ts
as a JSON-RPC request type for the 'eth_createAccessList' methodEthCreateAccessListJsonRpcResponse
is defined inpackages/actions/src/eth/EthJsonRpcResponse.ts
with a proper response structure includingaccessList
field- Both types are properly imported and used throughout the codebase, including in the procedure definitions and request handler
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the existence and implementation of the referenced types
# Test 1: Search for EthCreateAccessListJsonRpcRequest type definition
echo "Searching for EthCreateAccessListJsonRpcRequest..."
rg "EthCreateAccessListJsonRpcRequest" -A 5
# Test 2: Search for EthCreateAccessListJsonRpcResponse type definition
echo "Searching for EthCreateAccessListJsonRpcResponse..."
rg "EthCreateAccessListJsonRpcResponse" -A 5
Length of output: 5035
packages/actions/src/anvil/AnvilParams.ts (1)
167-174
: Verify the integration with related files.
The type looks well-structured, but let's verify its integration with other components.
✅ Verification successful
Let me gather more specific information about the integration by checking the actual implementation and type usage.
Let me check one final aspect to ensure complete verification of the integration.
Integration is properly implemented and consistent
The verification shows that AnvilDealParams
is well integrated across the codebase:
- Properly imported and used in
AnvilHandler.ts
,AnvilJsonRpcRequest.ts
- Correctly typed in JSON-RPC request/response chain
- Well-tested with both ERC20 and native token scenarios in
anvilDealProcedure.spec.ts
- Has a proper result type definition in
AnvilResult.ts
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the integration of AnvilDealParams with related files
# Test 1: Check if AnvilDealParams is properly imported and used
echo "Checking imports and usage of AnvilDealParams..."
rg -l "AnvilDealParams" --type ts
# Test 2: Verify the consistency of anvil_deal method implementation
echo "Checking anvil_deal method implementation..."
rg "anvil_deal" --type ts
Length of output: 1811
Script:
#!/bin/bash
# Check the actual implementation and type usage in AnvilHandler.ts
echo "Checking AnvilHandler.ts implementation..."
rg -A 5 "AnvilDealParams" packages/actions/src/anvil/AnvilHandler.ts
# Check the JSON-RPC request/response type definitions
echo "Checking JSON-RPC type definitions..."
cat packages/actions/src/anvil/AnvilJsonRpcRequest.ts | grep -A 5 "AnvilDealJsonRpcRequest"
# Check test implementation
echo "Checking test implementation..."
cat packages/actions/src/anvil/anvilDealProcedure.spec.ts
Length of output: 2521
Script:
#!/bin/bash
# Check the actual procedure implementation
echo "Checking anvil deal procedure implementation..."
cat packages/actions/src/anvil/anvilDealProcedure.ts
# Check the result type definition
echo "Checking result type definition..."
cat packages/actions/src/anvil/AnvilResult.ts | grep -A 5 "AnvilDealResult"
Length of output: 447
packages/decorators/src/actions/TevmActionsApi.ts (2)
2-2
: LGTM: Import follows existing patterns
The addition of AnvilDealHandler
to the imports is consistent with the existing handler types and follows the established pattern.
123-134
: Enhance documentation for security and usage clarity
While the implementation looks good, consider the following improvements to the documentation:
- Add a warning that this is for testing purposes only
- Document how decimals are handled for different tokens
- Use a generic address in the example instead of the actual USDC address
- Add a note about potential security implications of balance manipulation
Here's a suggested documentation improvement:
/**
* Deals ERC20 tokens to an account by overriding the storage of balanceOf(account)
+ * @notice This is a testing utility and should not be used in production
+ * @notice Token amounts should account for the token's decimals (e.g., 6 for USDC, 18 for most tokens)
* @example
* ```typescript
* await tevm.deal({
- * erc20: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // Optional: USDC address
+ * erc20: '0x1234...', // The ERC20 token address
* account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
- * amount: 1000000n // 1 USDC (6 decimals)
+ * amount: 1000000n // Amount in smallest unit (consider token decimals)
* })
* ```
+ * @warning This method directly manipulates storage slots and bypasses normal token transfer mechanics
*/
Let's verify if this functionality is properly gated in the implementation:
packages/actions/src/tevm-request-handler/EthReturnType.ts (2)
7-7
: LGTM! Import follows established patterns.
The new import is correctly placed and follows the existing alphabetical ordering.
85-85
: LGTM! Type mapping is properly integrated.
The new eth_createAccessList mapping follows the established pattern and enhances type safety for the new RPC method.
packages/actions/src/anvil/AnvilJsonRpcResponse.ts (2)
7-7
: LGTM: Import follows established patterns
The addition of AnvilDealResult
to the imports maintains consistency with existing patterns and proper ESM import syntax.
Line range hint 1-152
: Verify state handling implications
The file contains TODOs about aligning dump/load state functionality. Since anvil_deal
modifies account state, verify if these state handling improvements should be addressed first:
// Relevant TODOs in file:
// TODO make this the same as our dump state
// TODO make this the same as our load state
Let's check for state handling dependencies:
packages/actions/src/anvil/AnvilJsonRpcRequest.ts (2)
4-4
: LGTM: Import statement follows project conventions
The import statement is properly placed and follows the existing patterns in the file.
136-136
: LGTM: Union type properly updated
The AnvilDealJsonRpcRequest is correctly added to the union type, maintaining consistency with the existing pattern.
packages/actions/src/anvil/AnvilProcedure.ts (4)
Line range hint 2-18
: LGTM: Import declarations are well-structured
The new AnvilDealJsonRpcRequest
import is correctly added and follows the established pattern.
Line range hint 19-35
: LGTM: Response type imports are properly organized
The new AnvilDealJsonRpcResponse
import is correctly added and maintains consistency with existing response types.
131-146
: LGTM: Union type correctly updated
The AnvilDealProcedure
is properly added to the AnvilProcedure
union type, maintaining type safety and consistency.
Line range hint 1-146
: Verify integration with related components
The type definitions look good, but let's verify the integration with related components.
✅ Verification successful
Integration looks complete and well-tested
The verification shows proper integration:
- Comprehensive test coverage in
anvilDealProcedure.spec.ts
covering both ERC20 and native token scenarios - Complete implementation with proper handler, procedure, request/response types, and results
- Well-documented procedure with JSDoc examples
- Proper error handling in place
The only missing elements (client/transport directories) appear to be due to a different repository structure, which is expected as these are likely handled at a higher level.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify proper integration of anvil_deal procedure
# Check for corresponding handler implementation
echo "Checking for AnvilDealHandler implementation..."
rg "class.*AnvilDealHandler|interface.*AnvilDealHandler" -t ts
# Check for corresponding test files
echo "Checking for related test files..."
fd -e test.ts -e spec.ts . | rg -i "anvildeal"
# Check for documentation updates
echo "Checking for documentation updates..."
fd "README.md" | xargs rg -l "anvil_deal"
Length of output: 474
Script:
#!/bin/bash
# Let's check the test file content and handler implementation
echo "Checking test file content..."
cat packages/actions/src/anvil/anvilDealProcedure.spec.ts
echo -e "\nChecking for handler implementation..."
rg "anvil_deal" -A 5 -B 5 packages/actions/src/anvil/
echo -e "\nChecking for usage in client/transport..."
rg "AnvilDealProcedure|anvil_deal" packages/actions/src/client/ packages/actions/src/transport/
Length of output: 12596
packages/actions/src/eth/EthProcedure.ts (3)
7-7
: LGTM: Import addition follows conventions
The new import maintains alphabetical order and follows the established pattern.
48-48
: LGTM: Response type import follows conventions
The new response type import maintains alphabetical order and follows the established pattern.
212-215
: Verify procedure integration and implementation
Let's ensure the new procedure is properly integrated:
✅ Verification successful
Let me gather more specific information about the implementation and test coverage.
Let me check for the actual implementation file since we've seen the tests and integration but not the core implementation.
Procedure is properly integrated and implemented
The verification shows a complete and proper integration:
- Implementation exists in
ethCreateAccessListProcedure.js
with proper error handling and type safety - Comprehensive test coverage with contract deployment and RPC call testing
- Correctly registered in
TevmJsonRpcRequestHandler.ts
with proper documentation - Types properly defined in request/response interfaces
- Properly exported through the package index
The procedure is well-integrated into the codebase with all necessary components in place.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the integration and implementation of eth_createAccessList
# Test 1: Check if the procedure is registered in handlers
echo "Checking procedure registration..."
rg -l "eth_createAccessList" --type ts
# Test 2: Look for implementation file
echo "Looking for implementation..."
fd -e ts -e js createAccessList
# Test 3: Check for test coverage
echo "Checking test coverage..."
fd -e spec.ts -e test.ts createAccessList
Length of output: 700
Script:
#!/bin/bash
# Check the actual implementation and test details
# Look at the test file content
echo "=== Test Implementation ==="
cat packages/actions/src/eth/ethCreateAccessListProcedure.spec.ts
# Check how it's integrated in the request handler
echo -e "\n=== Handler Integration ==="
rg -A 5 -B 5 "eth_createAccessList" packages/actions/src/tevm-request-handler/TevmJsonRpcRequestHandler.ts
# Check the request/response type definitions
echo -e "\n=== Type Definitions ==="
rg -A 3 "EthCreateAccessList" packages/actions/src/eth/EthJsonRpcRequest.ts
rg -A 3 "EthCreateAccessList" packages/actions/src/eth/EthJsonRpcResponse.ts
Length of output: 3046
Script:
#!/bin/bash
# Check the implementation file
echo "=== Implementation ==="
cat packages/actions/src/eth/ethCreateAccessListProcedure.js || cat packages/actions/src/eth/ethCreateAccessListProcedure.ts
# Check if it's exported properly
echo -e "\n=== Exports Check ==="
rg -A 2 "export.*ethCreateAccessListProcedure" packages/actions/src/eth/
Length of output: 2598
packages/actions/src/createHandlers.js (3)
8-8
: LGTM: New imports follow established patterns.
The new imports for anvilDealJsonRpcProcedure
and ethCreateAccessListProcedure
maintain consistency with the existing import structure and naming conventions.
Also applies to: 29-29
97-97
: LGTM: New eth handler follows established patterns.
The addition of eth_createAccessList
handler maintains consistency with existing handler patterns and is correctly placed in alphabetical order.
151-151
: Verify namespace mappings for the new anvil_deal handler.
The anvil_deal
handler addition looks good. Let's verify that the namespace mappings are correctly generated.
✅ Verification successful
Let me gather more information about the namespace mappings implementation to verify this thoroughly.
Namespace mappings for anvil_deal are correctly implemented
The codebase shows that all anvil handlers, including the new anvil_deal
, are automatically mapped to other namespaces through Object.fromEntries
transformations:
tevm_deal
viakey.replace('anvil', 'tevm')
ganache_deal
viakey.replace('anvil', 'ganache')
hardhat_deal
viakey.replace('anvil', 'hardhat')
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that the new anvil_deal handler is correctly mapped across all namespaces
# Test: Search for all deal-related handlers. Expect: anvil_deal, tevm_deal, ganache_deal, hardhat_deal
rg --type js "(?:anvil|tevm|ganache|hardhat)_deal.*?:" -A 1
Length of output: 243
Script:
#!/bin/bash
# Check the implementation of namespace mappings
rg --type js "const \w+Handlers = Object\.fromEntries" -A 5 -B 5
Length of output: 1661
packages/actions/src/eth/EthJsonRpcRequest.ts (1)
14-14
: Verify the impact of making from
optional.
Making the from
field optional is technically correct per Ethereum JSON-RPC spec, but this is a breaking change that could affect existing code.
Let's verify the usage:
✅ Verification successful
Let me gather more information to verify the impact comprehensively.
Based on the search results, I can now generate the final response:
Making from
optional is safe and aligns with Ethereum JSON-RPC spec
The change to make from
optional in JsonRpcTransaction
is safe because:
- No code in the codebase assumes
from
is required through destructuring or direct access - The type is used consistently in RPC method parameters (
eth_call
,eth_estimateGas
,eth_sendTransaction
,eth_createAccessList
) wherefrom
is indeed optional per Ethereum spec - No interfaces extend
JsonRpcTransaction
that might be affected by this change
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for code that assumes `from` is required
# Look for destructuring or direct access without optional chaining
rg -g '*.{ts,js}' 'const.*\{.*from.*\}.*:.*JsonRpcTransaction|\.from\s+=' -A 2
Length of output: 1208
Script:
#!/bin/bash
# Search for all usages of JsonRpcTransaction type and from field
rg -g '*.{ts,js}' 'JsonRpcTransaction' -B 2 -A 2
# Also search for any code that might be validating the from field
rg -g '*.{ts,js}' 'from.*required|required.*from' -B 2 -A 2
# Look for type extensions or implementations
ast-grep --pattern 'interface $_ extends JsonRpcTransaction'
Length of output: 2463
packages/actions/src/anvil/anvilDealHandler.js (3)
16-21
: Logic appropriately handles non-ERC20 balances
The code correctly delegates to setAccountHandler
to set the account's balance directly when erc20
is not provided. This ensures that non-ERC20 balances are handled properly.
23-23
: Conversion of amount to 32-byte hex string is correct
Using numberToHex(amount, { size: 32 })
accurately converts the amount into a 32-byte hexadecimal string, which is suitable for storage operations.
46-56
:
Verify that modified storage slots correspond to the balance mapping
Relying solely on the access list from eth_createAccessList
may not guarantee that the storage slots correspond to the ERC20 balanceOf
mapping, especially if the contract uses a non-standard storage layout or proxy patterns. It's important to ensure that you're modifying the correct storage slots to prevent unintended side effects.
To confirm that the storage slots correspond to the balanceOf
mapping, you can analyze the contract's storage layout. Here's a script to help verify the correct storage slot:
Ensure that the storage slot you're modifying matches the balanceOf
mapping slot in the ERC20 contract.
✅ Verification successful
Based on the gathered information, I can now provide the final response:
The storage slot determination is secure through eth_createAccessList
The implementation correctly identifies the storage slots by simulating a balanceOf
call through eth_createAccessList
. This is a secure approach because:
- It uses the actual contract's storage layout by simulating the exact
balanceOf
function call - The access list returned contains only the storage slots that are actually accessed during the
balanceOf
execution - The implementation doesn't make assumptions about the storage layout but rather lets the EVM identify the correct slots
The review comment's concern about non-standard storage layouts or proxy patterns is addressed because eth_createAccessList
will return the correct storage slots regardless of the contract's implementation details.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the storage slot for the balance mapping in the ERC20 contract.
# Test: Retrieve the storage layout of the contract to identify the balance mapping slot.
# Expected result: The slot used corresponds to the standard ERC20 balance mapping slot (usually slot 0).
# Fetch the contract's ABI and storage layout using `cast` (if available) or other tools.
# Note: Replace `<YOUR_ETH_NODE_URL>` with your Ethereum node URL.
# Fetch the contract's source code and storage layout (requires source verification)
curl -X POST -H "Content-Type: application/json" --data '{
"jsonrpc":"2.0",
"method":"eth_getCode",
"params":["'"$erc20"'", "latest"],
"id":1
}' <YOUR_ETH_NODE_URL>
# Analyze the storage layout to find the slot for `balanceOf`
# Since this script requires interaction with an Ethereum node and possibly Etherscan API, please ensure you have access and replace placeholders accordingly.
Length of output: 167
Script:
#!/bin/bash
# Let's analyze the code to understand how the storage slots are obtained and used
# First, let's find where accessListResponse is generated
rg -A 5 "accessListResponse" --type js
# Then check for any tests or documentation about storage slots
rg -l "storage.*slot|slot.*storage" --type js
# Look for any related anvil storage manipulation code
rg -A 5 "anvil_setStorageAt" --type js
# Check for any documentation about storage slot handling
fd README.md | xargs rg "storage"
Length of output: 5635
Script:
#!/bin/bash
# Let's examine how the storage slots are determined through eth_createAccessList
# Check the context around eth_createAccessList usage
rg -B 10 -A 10 "eth_createAccessList" --type js
# Look for any test files that might provide insights
fd test -t f | xargs rg "eth_createAccessList|anvil_setStorageAt"
# Check for any ERC20-related code that might show how balances are handled
rg -A 5 "balanceOf" --type js
Length of output: 18637
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: {}, | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance test coverage for native token dealing.
Similar to the ERC20 test case, this test could benefit from additional verifications and documentation.
Consider applying these improvements:
it('should deal native tokens when no erc20 address provided', async () => {
const client = createTevmNode()
+ const account = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
+ const amount = '0xde0b6b3a7640000' // 1 ETH (1e18 wei)
+ // Get initial balance
+ const initialBalance = await client.getBalance({
+ address: account,
+ })
const result = await anvilDealJsonRpcProcedure(client)({
method: 'anvil_deal',
params: [
{
- account: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
- amount: '0xde0b6b3a7640000', // 1 ETH
+ account,
+ amount,
},
],
id: 1,
jsonrpc: '2.0',
})
+ // Verify balance increase
+ const finalBalance = await client.getBalance({
+ address: account,
+ })
+ expect(finalBalance - initialBalance).toBe(BigInt(amount))
expect(result).toEqual({
jsonrpc: '2.0',
id: 1,
method: 'anvil_deal',
- result: {},
+ result: {
+ success: true,
+ balance: amount,
+ },
})
})
Committable suggestion skipped: line range outside the PR's diff.
// test createAccessList with JSON-RPC format | ||
const result = await ethCreateAccessListProcedure(client)({ | ||
method: 'eth_createAccessList', | ||
params: [ | ||
{ | ||
data: encodeFunctionData({ | ||
abi: erc20.abi, | ||
functionName: 'balanceOf', | ||
args: [erc20.address], | ||
}), | ||
to: erc20.address, | ||
}, | ||
], | ||
id: 1, | ||
jsonrpc: '2.0', | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add test cases for edge cases and error scenarios.
Consider adding test cases for:
- Invalid contract addresses
- Invalid function signatures
- Empty or malformed parameters
- Gas estimation edge cases
Would you like me to help generate additional test cases for these scenarios?
expect( | ||
( | ||
await setAccountHandler(client)({ | ||
address: erc20.address, | ||
deployedBytecode: erc20.deployedBytecode, | ||
}) | ||
).errors, | ||
).toBeUndefined() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance contract deployment assertions.
While checking for undefined errors is good, consider adding positive assertions to verify the contract was deployed successfully, such as checking the contract code at the deployed address.
expect(
(
await setAccountHandler(client)({
address: erc20.address,
deployedBytecode: erc20.deployedBytecode,
})
).errors,
).toBeUndefined()
+// Add verification of successful deployment
+const code = await client.request({
+ method: 'eth_getCode',
+ params: [erc20.address, 'latest']
+})
+expect(code).toBe(erc20.deployedBytecode)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
expect( | |
( | |
await setAccountHandler(client)({ | |
address: erc20.address, | |
deployedBytecode: erc20.deployedBytecode, | |
}) | |
).errors, | |
).toBeUndefined() | |
expect( | |
( | |
await setAccountHandler(client)({ | |
address: erc20.address, | |
deployedBytecode: erc20.deployedBytecode, | |
}) | |
).errors, | |
).toBeUndefined() | |
// Add verification of successful deployment | |
const code = await client.request({ | |
method: 'eth_getCode', | |
params: [erc20.address, 'latest'] | |
}) | |
expect(code).toBe(erc20.deployedBytecode) |
expect(result).toMatchInlineSnapshot(` | ||
{ | ||
"id": 1, | ||
"jsonrpc": "2.0", | ||
"method": "eth_createAccessList", | ||
"result": { | ||
"accessList": [ | ||
{ | ||
"address": "0x0000000000000000000000000000000000066a44", | ||
"storageKeys": [ | ||
"0xf1accc61b11ca39f2c1d4ba4a393d616196b642a5f638560763cb25d022dff56", | ||
], | ||
}, | ||
], | ||
"gasUsed": "0x5e0f", | ||
}, | ||
} | ||
`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add explicit assertions alongside the snapshot.
While snapshots are useful, consider adding explicit assertions to make the test's expectations clearer and more maintainable.
+// Add explicit assertions before the snapshot
+expect(result.result.accessList).toHaveLength(1)
+expect(result.result.accessList[0].address).toBe(erc20.address)
+expect(result.result.accessList[0].storageKeys).toHaveLength(1)
+expect(result.result.gasUsed).toBeTruthy()
+
expect(result).toMatchInlineSnapshot(/* ... */)
// Convert the accessList from Record<Address, Set<Hex>> to the expected format | ||
const formattedAccessList = Object.entries(response.result.accessList).map(([address, storageKeys]) => ({ | ||
address: /** @type {import('abitype').Address}*/ (address), | ||
storageKeys: Array.from(storageKeys), | ||
})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding address format validation
While the type assertion ensures TypeScript compatibility, runtime validation of the address format would improve reliability.
Consider adding validation:
+const isValidAddress = (addr) => /^0x[0-9a-fA-F]{40}$/.test(addr)
+
const formattedAccessList = Object.entries(response.result.accessList).map(([address, storageKeys]) => ({
+ if (!isValidAddress(address)) {
+ throw new Error(`Invalid address format: ${address}`)
+ }
address: /** @type {import('abitype').Address}*/ (address),
storageKeys: Array.from(storageKeys),
}))
Committable suggestion skipped: line range outside the PR's diff.
...(request.id !== undefined ? { id: request.id } : {}), | ||
method: 'anvil_deal', | ||
error: { | ||
// @ts-expect-error being lazy here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolve TypeScript errors instead of suppressing them
The comment // @ts-expect-error being lazy here
indicates suppression of a TypeScript error without proper resolution. It's better to address the underlying type issue to improve code quality and maintainability.
Apply this diff to fix the TypeScript error:
- // @ts-expect-error being lazy here
code: (result.errors[0]?.code ?? -32000).toString(),
+ // Ensure 'code' is of the correct type
+ code: result.errors[0]?.code ?? -32000,
Committable suggestion skipped: line range outside the PR's diff.
const [{ erc20, account, amount }] = request.params | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add validation for request parameters to prevent runtime errors
The code assumes that request.params
is an array with at least one object. If request.params
is undefined, empty, or not structured as expected, this could cause a runtime error. Adding validation for request.params
will improve robustness.
Apply this diff to add parameter validation:
export const anvilDealJsonRpcProcedure = (client) => async (request) => {
+ if (!Array.isArray(request.params) || request.params.length === 0 || typeof request.params[0] !== 'object') {
+ return {
+ jsonrpc: request.jsonrpc,
+ ...(request.id !== undefined ? { id: request.id } : {}),
+ error: {
+ code: -32602,
+ message: 'Invalid params: Expected an array with at least one object.',
+ },
+ }
+ }
const [{ erc20, account, amount }] = request.params
Committable suggestion skipped: line range outside the PR's diff.
const result = await dealHandler(client)({ | ||
...(erc20 !== undefined ? { erc20 } : {}), | ||
account, | ||
amount: hexToBigInt(amount), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle potential errors when converting 'amount' with 'hexToBigInt'
If amount
is not a valid hex string, hexToBigInt(amount)
may throw an error. To prevent runtime exceptions, add error handling or input validation for amount
.
Apply this diff to include error handling:
+ let parsedAmount
+ try {
+ parsedAmount = hexToBigInt(amount)
+ } catch (error) {
+ return {
+ jsonrpc: request.jsonrpc,
+ ...(request.id !== undefined ? { id: request.id } : {}),
+ error: {
+ code: -32602,
+ message: 'Invalid amount parameter: must be a valid hex string.',
+ },
+ }
+ }
And update the amount
assignment:
- amount: hexToBigInt(amount),
+ amount: parsedAmount,
Committable suggestion skipped: line range outside the PR's diff.
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 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling for exceptions thrown by 'dealHandler'
If dealHandler
throws an exception, the current code does not catch it, which may lead to unhandled promise rejections. Wrapping the dealHandler
call in a try-catch block will ensure proper error handling and return a valid JSON-RPC error response.
Apply this diff to add error handling:
export const anvilDealJsonRpcProcedure = (client) => async (request) => {
const [{ erc20, account, amount }] = request.params
+ try {
const result = await dealHandler(client)({
...(erc20 !== undefined ? { erc20 } : {}),
account,
amount: hexToBigInt(amount),
})
if ('errors' in result && result.errors) {
const out = {
jsonrpc: request.jsonrpc,
...(request.id !== undefined ? { id: request.id } : {}),
- method: 'anvil_deal',
error: {
code: result.errors[0]?.code ?? -32000,
message: result.errors[0]?.message ?? result.errors[0]?.name ?? 'An unknown error occurred',
},
}
return out
}
return {
jsonrpc: request.jsonrpc,
...(request.id !== undefined ? { id: request.id } : {}),
- method: 'anvil_deal',
result: {},
}
+ } catch (error) {
+ return {
+ jsonrpc: request.jsonrpc,
+ ...(request.id !== undefined ? { id: request.id } : {}),
+ error: {
+ code: -32603,
+ message: error.message || 'Internal error',
+ },
+ }
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
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 | |
} | |
try { | |
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 } : {}), | |
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 } : {}), | |
result: {}, | |
} | |
} catch (error) { | |
return { | |
jsonrpc: request.jsonrpc, | |
...(request.id !== undefined ? { id: request.id } : {}), | |
error: { | |
code: -32603, | |
message: error.message || 'Internal error', | |
}, | |
} | |
} |
if (!accessListResponse.result?.accessList) { | ||
throw new Error('Failed to get access list') | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enhance error handling for access list retrieval failure
The current error message might not provide sufficient context for debugging. Consider including additional details about the failure to aid in troubleshooting.
Apply this diff to improve the error message:
-if (!accessListResponse.result?.accessList) {
- throw new Error('Failed to get access list')
+if (!accessListResponse.result?.accessList) {
+ throw new Error(`Failed to retrieve access list for ERC20 contract at address ${erc20}`)
}
Committable suggestion skipped: line range outside the PR's diff.
Description
Concise description of proposed changes
Testing
Explain the quality checks that have been done on the code changes
Additional Information
Your ENS/address:
Summary by CodeRabbit
Release Notes
New Features
anvil_deal
JSON-RPC request for handling ERC20 token transactions.eth_createAccessList
JSON-RPC request to create access lists for Ethereum transactions.deal
method in theTevmActionsApi
for ERC20 token distribution.Bug Fixes
Tests
anvil_deal
andeth_createAccessList
procedures to validate functionality.