Skip to content

Commit

Permalink
feat(deal): rename recipient and add default account
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The `recipient` parameter of the `deal` function has been renamed to `account` and is now optional. If no account is provided, the default account of the client is used.
  • Loading branch information
Rubilmax committed Oct 14, 2024
1 parent 170ea62 commit fb26986
Show file tree
Hide file tree
Showing 11 changed files with 467 additions and 247 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ Easily [deal](https://book.getfoundry.sh/cheatcodes/deal) arbitrary amounts of a

> NB: `deal` is the name of a cheat code introduced by foundry, which "mints" without actually minting ERC20 tokens - it's overriding the storage of the balance of the given recipient
The storage slot of the mapping `balanceOf` is brute-forced and the given user's balance is manipulated via `setStorageAt`.

Storage slots are cached at `cache/viem-deal.json` to avoid brute-forcing slots every time.
The storage slot of the mapping `balanceOf` is retrieved via `eth_createAccessList` and the given user's balance is manipulated via `setStorageAt`.

## Installation

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,14 @@
"@biomejs/biome": "^1.9.3",
"@commitlint/cli": "^19.5.0",
"@commitlint/config-conventional": "^19.5.0",
"@types/lodash.kebabcase": "^4.1.9",
"@types/node": "^22.7.4",
"@vitest/coverage-v8": "^2.1.2",
"conventional-changelog-conventionalcommits": "^8.0.0",
"dotenv-cli": "^7.4.2",
"husky": "^9.1.6",
"lint-staged": "^15.2.10",
"prool": "^0.0.16",
"lodash.kebabcase": "^4.1.1",
"typescript": "^5.6.2",
"viem": "^2.21.18",
"vitest": "^2.1.2"
Expand Down
31 changes: 21 additions & 10 deletions src/actions/test/deal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
type ExactPartial,
type GetStorageAtErrorType,
type Hash,
type PartialBy,
type Quantity,
type ReadContractErrorType,
type SetStorageAtErrorType,
Expand All @@ -19,7 +20,8 @@ import {
erc20Abi,
numberToHex,
} from "viem";
import { getStorageAt, readContract, setStorageAt } from "viem/actions";
import { parseAccount } from "viem/accounts";
import { getStorageAt, readContract, setBalance, setStorageAt } from "viem/actions";

export type CreateAccessListRpcSchema = {
Method: "eth_createAccessList";
Expand All @@ -32,19 +34,23 @@ export type CreateAccessListRpcSchema = {
};
};

export type DealParameters = {
export type RawDealParameters = {
/* The address of the ERC20 token to deal. */
erc20: Address;
/* The address of the recipient of the dealt tokens. */
recipient: Address;
erc20?: Address;
/* The owner of the dealt tokens. */
account: Account | Address;
/* The amount of tokens to deal. */
amount: bigint;
};

export type DealParameters<account extends Account | undefined = Account | undefined> = account extends Account
? PartialBy<RawDealParameters, "account">
: RawDealParameters;

export type DealErrorType = GetStorageAtErrorType | SetStorageAtErrorType | ReadContractErrorType;

/**
* Deals ERC20 tokens to a recipient, by overriding the storage of `balanceOf(recipient)`.
* Deals ERC20 tokens to an account, by overriding the storage of `balanceOf(account)`.
*
* - Docs: https://viem.sh/docs/actions/test/deal
*
Expand All @@ -63,14 +69,19 @@ export type DealErrorType = GetStorageAtErrorType | SetStorageAtErrorType | Read
* })
* await deal(client, {
* erc20: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
* recipient: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
* account: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
* amount: parseUnits("100", 6),
* })
*/
export async function deal<chain extends Chain | undefined, account extends Account | undefined>(
client: TestClient<TestClientMode, Transport, chain, account, false>,
{ erc20, recipient, amount }: DealParameters,
{ erc20, account: account_ = client.account!, amount }: DealParameters<account>,
) {
const account = parseAccount(account_);

if (erc20 == null || erc20 === "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE")
return setBalance(client, { address: account.address, value: amount });

const value = numberToHex(amount, { size: 32 });

const { accessList } = await client.request<CreateAccessListRpcSchema>({
Expand All @@ -81,7 +92,7 @@ export async function deal<chain extends Chain | undefined, account extends Acco
data: encodeFunctionData({
abi: erc20Abi,
functionName: "balanceOf",
args: [recipient],
args: [account.address],
}),
},
],
Expand All @@ -101,7 +112,7 @@ export async function deal<chain extends Chain | undefined, account extends Acco
abi: erc20Abi,
address: erc20,
functionName: "balanceOf",
args: [recipient],
args: [account.address],
});

if (balance === amount) return;
Expand Down
6 changes: 3 additions & 3 deletions src/dealActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { TestClientMode } from "node_modules/viem/_types/clients/createTest
import type { Account, Chain, TestClient, Transport } from "viem";
import { type DealParameters, deal } from "./actions/test/deal.js";

export type DealActions = {
export type DealActions<account extends Account | undefined = Account | undefined> = {
/**
* Deals ERC20 tokens to a recipient, by overriding the storage of `balanceOf(recipient)`.
*
Expand All @@ -24,13 +24,13 @@ export type DealActions = {
* amount: parseUnits("100", 6),
* })
*/
deal: (args: DealParameters) => Promise<void>;
deal: (args: DealParameters<account>) => Promise<void>;
};

export function dealActions<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
>(client: TestClient<TestClientMode, Transport, chain, account, false>): DealActions {
>(client: TestClient<TestClientMode, Transport, chain, account, false>): DealActions<account> {
return {
deal: (args) => deal(client, args),
};
Expand Down
Loading

0 comments on commit fb26986

Please sign in to comment.