A Foundry project that implements minimal smart contract accounts for two account abstraction models:
- Ethereum / EVM: an ERC-4337-style account that validates
PackedUserOperationsignatures through anEntryPoint. - zkSync Era: a native zkSync account that validates and executes transactions through the Era bootloader flow.
The repository is intentionally small and educational. It focuses on the core mechanics of account validation, owner-authorized execution, prefunding, and transaction forwarding without adding production wallet features such as recovery modules, batching, session keys, paymaster policy, or upgradeability.
MinimalAccount is a lightweight ERC-4337 account implementation.
It supports:
- Owner-controlled execution through
execute. - EntryPoint-controlled execution for validated user operations.
- ECDSA signature validation against the account owner.
- Prefunding of missing EntryPoint funds during validation.
- Direct ETH receives so the account can pay for execution.
The account trusts a configured IEntryPoint and only allows validateUserOp to be called by that EntryPoint.
ZkMinimalAccount implements zkSync Era's native IAccount interface.
It supports:
- Transaction validation through the bootloader.
- Owner-controlled execution.
- Execution from outside the bootloader when the transaction signature is valid.
- Nonce handling through zkSync's nonce holder system contract.
- Fee payment through
payToTheBootloader. - System-contract-aware execution for deployments.
The zkSync account validates signatures against the owner and returns ACCOUNT_VALIDATION_SUCCESS_MAGIC when validation succeeds.
| Contract | Description |
|---|---|
src/ethereum/MinimalAccount.sol |
Minimal ERC-4337 account controlled by an owner and an EntryPoint. |
src/zksync/ZkMinimalAccount.sol |
Minimal zkSync Era native account controlled by an owner and the bootloader. |
| Script | Description |
|---|---|
script/DeployMinimalAccount.s.sol |
Deploys the EVM MinimalAccount and transfers ownership to the configured account. |
script/HelperConfig.s.sol |
Provides network-specific EntryPoint and account configuration. Local Anvil deployments create a fresh EntryPoint. |
script/SendPackedUserOp.s.sol |
Builds, signs, and sends a PackedUserOperation through the configured EntryPoint. |
- Foundry
- Git submodules enabled for dependencies
- Node.js / Yarn only for the zkSync helper commands that use
yarnornpx foundryup-zksyncfor zkSync build and test flows
git clone https://github.com/BuildsWithKing/minimal-account-abstraction
cd minimal-account-abstraction
forge installIf you prefer the provided dependency pins, use:
make installThe project uses:
forge-std- OpenZeppelin Contracts
eth-infinitism/account-abstractionfoundry-era-contractsfoundry-devops
Build the EVM contracts:
make buildRun the EVM test suite:
make testRun formatting:
make formatBuild with zkSync tooling:
make zkbuildRun zkSync tests:
make zktestThe GitHub Actions workflow runs:
forge fmt --check
forge build --sizes
forge test -vvvStart a local EVM chain:
make anvilThe local config deploys a fresh EntryPoint when running against chain id 31337.
Start a local zkSync development node:
make zkanvilThe Makefile includes a deployment command:
make deployEthThis expects environment variables and Foundry account configuration used by the command, including:
SMALL_MONEY_SENDER- a Foundry keystore account named
smallmoney - an RPC alias named
arbitrum ETHERSCAN_API_KEYwhen verification is enabled
After deploying MinimalAccount, send a packed user operation with:
make sendUserOpSendPackedUserOp currently builds a user operation that calls approve(address,uint256) on the configured token through the account's execute function.
The Makefile includes zkSync-oriented helpers:
make zkdeploy
make sendTxThese commands delegate to Yarn scripts, so ensure the corresponding package scripts exist before using them.
.
|-- src
| |-- ethereum
| | `-- MinimalAccount.sol
| `-- zksync
| `-- ZkMinimalAccount.sol
|-- script
| |-- DeployMinimalAccount.s.sol
| |-- HelperConfig.s.sol
| `-- SendPackedUserOp.s.sol
|-- test
| |-- ethereum
| | `-- MinimalAccountTest.t.sol
| `-- zksync
| `-- ZkMinimalAccountTest.t.sol
|-- foundry.toml
`-- Makefile
The EVM tests cover:
- Owner execution.
- Rejection of unauthorized execution.
- Signed user operation recovery.
- EntryPoint validation.
- EntryPoint execution through
handleOps.
The zkSync tests cover:
- Owner execution.
- Bootloader transaction validation.
- External execution with a valid signed transaction.
This code is a minimal learning implementation and has not been audited.
Before using similar logic in production, consider:
- Strong replay protection and nonce handling for all target networks.
- More complete gas accounting and prefund behavior.
- Signature scheme flexibility, including EIP-1271 or modular validation.
- Recovery flows and owner rotation safety.
- Paymaster restrictions and validation policy.
- Extensive fuzzing, invariant testing, and external review.
MIT