[Phase 1] Basic On-Chain Transaction Simulation (MVP)
- Dominant language
- JavaScript
- Stars
- 2
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Overview
Implement basic on-chain transaction simulation using ERC-4337 EntryPoint's built-in simulation capabilities. This is the MVP that provides core simulation functionality before users sign with their passkey.
## Parent Issue
#140 - Implement Transaction Simulation for Enhanced Wallet Security
## Background
EthAura already has EntryPointSimulations in the codebase:
- `lib/account-abstraction/contracts/core/EntryPointSimulations.sol`
- Test utilities in `lib/account-abstraction/test/UserOp.ts`
These need to be ported to the frontend for pre-execution simulation.
## Technical Approach
### Using State Override for Simulation
```javascript
// State override approach - temporarily replace EntryPoint code with simulation version
const stateOverride = {
[entryPointAddress]: {
code: EntryPointSimulationsJson.deployedBytecode
}
}
const result = await provider.send('eth_call', [tx, 'latest', stateOverride])
```
### Core Functions to Implement
```javascript
// frontend/src/lib/transactionSimulator.js
/**
* Simulate UserOperation validation
* @param {Object} userOp - PackedUserOperation
* @param {string} entryPointAddress - EntryPoint contract address
* @returns {Promise}
*/
export async function simulateValidation(userOp, entryPointAddress) {
const entryPointSimulations = new ethers.Interface(EntryPointSimulationsABI)
const data = entryPointSimulations.encodeFunctionData('simulateValidation', [userOp])
const tx = {
to: entryPointAddress,
data,
}
const stateOverride = {
[entryPointAddress]: {
code: EntryPointSimulationsJson.deployedBytecode
}
}
const result = await provider.send('eth_call', [tx, 'latest', stateOverride])
return decodeValidationResult(result)
}
/**
* Simulate full UserOperation execution
* @param {Object} userOp - PackedUserOperation
* @param {string} target - Target contract address
* @param {string} targetCallData - Calldata for target
* @param {string} entryPointAddress - EntryPoint contract address
* @returns {Promise}
*/
export async function simulateHandleOp(userOp, target, targetCallData, entryPointAddress) {
const entryPointSimulations = new ethers.Interface(EntryPointSimulationsABI)
const data = entryPointSimulations.encodeFunctionData('simulateHandleOp', [userOp, target, targetCallData])
const tx = {
to: entryPointAddress,
data,
}
const stateOverride = {
[entryPointAddress]: {
code: EntryPointSimulationsJson.deployedBytecode
}
}
const result = await provider.send('eth_call', [tx, 'latest', stateOverride])
return decodeExecutionResult(result)
}
/**
* High-level simulation function
*/
export async function simulateUserOperation(userOp, provider, entryPointAddress) {
try {
// 1. Validate the UserOp will be accepted
const validationResult = await simulateValidation(userOp, entryPointAddress)
// 2. Simulate the full execution
const executionResult = await simulateHandleOp(
userOp,
userOp.sender, // target is the account itself
userOp.callData,
entryPointAddress
)
return {
success: true,
willSucceed: executionResult.targetSuccess,
gasUsed: executionResult.paid,
preOpGas: executionResult.preOpGas,
validationData: validationResult,
revertReason: null,
}
} catch (error) {
return {
success: false,
willSucceed: false,
gasUsed: 0n,
revertReason: parseRevertReason(error),
}
}
}
```
## Tasks
### Core Implementation
- [ ] Create `frontend/src/lib/transactionSimulator.js`
- [ ] Export EntryPointSimulations ABI and bytecode for frontend use
- [ ] Implement `simulateValidation()` function
- [ ] Implement `simulateHandleOp()` function
- [ ] Implement `simulateUserOperation()` high-level wrapper
- [ ] Add revert reason parsing (`parseRevertReason()`)
### Integration with Transaction Flow
- [ ] Modify `TransactionSender.jsx` to call simulation before passkey prompt
- [ ] Add simulation loading state ("Simulating transaction...")
- [ ] Show simulation result before asking for signature
- [ ] Block transaction if simulation fails (with option to proceed anyway)
### UI Components
- [ ] Create `SimulationStatus.jsx` component:
- Loading spinner during simulation
- Success state with green checkmark
- Failed state with red X and revert reason
- [ ] Display estimated gas from simulation
- [ ] Show revert reason in user-friendly format
### Error Handling
- [ ] Handle RPC errors (network issues)
- [ ] Handle simulation timeout
- [ ] Provide fallback if state override not supported
- [ ] Map common revert reasons to user-friendly messages:
| Revert Reason | User Message |
|---------------|---------------|
| `AA21 didn't pay prefund` | "Insufficient ETH for gas" |
| `AA23 reverted` | "Transaction will fail" |
| `AA24 signature error` | "Invalid signature" |
| `AA25 invalid nonce` | "Nonce mismatch - refresh and try again" |
## Files to Create
1. **`frontend/src/lib/transactionSimulator.js`** - Core simulation logic
2. **`frontend/src/lib/entryPointSimulationsABI.js`** - ABI export
3. **`frontend/src/components/SimulationStatus.jsx`** - Status display component
4. **`frontend/src/styles/SimulationStatus.css`** - Styling
## Files to Modify
1. **`frontend/src/components/TransactionSender.jsx`** - Add simulation step
2. **`frontend/src/screens/SwapConfirmationScreen.jsx`** - Show simulation results
3. **`frontend/src/lib/constants.js`** - Add simulation-related constants
## Acceptance Criteria
- [ ] UserOperation is simulated before passkey prompt appears
- [ ] User sees loading state during simulation
- [ ] User sees if transaction will succeed or fail
- [ ] Revert reason is shown in user-friendly format if simulation fails
- [ ] Gas estimate from simulation is displayed
- [ ] User can still proceed with failed simulation (with warning)
- [ ] Simulation works for both ETH transfers and token swaps
## Testing
- [ ] Test simulation with valid transaction (should succeed)
- [ ] Test simulation with insufficient balance (should show revert)
- [ ] Test simulation with bad signature (should show error)
- [ ] Test simulation timeout handling
- [ ] Test UI states (loading, success, failed)
## Dependencies
None - this is the foundation phase.
## Estimated Effort
**Medium** - 2-3 days
## Labels
`security`, `enhancement`, `frontend`
Contributor guide
Research direction
Start by reading lib/account-abstraction/contracts/core/EntryPointSimulations.sol and lib/account-abstraction/test/UserOp.ts, then inspect the listed frontend transaction-flow files. The work spans transactionSimulator.js, SimulationStatus.jsx, and integration points in TransactionSender.jsx and SwapConfirmationScreen.jsx. Done means simulation runs before signing, reports loading, success, gas, and user-friendly failures for transfers and swaps.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- blockchain, frontend, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100