hadv / hadv/ethaura

[Phase 1] Basic On-Chain Transaction Simulation (MVP)

Open
#141 0 comments 0 reactions 0 assignees View on GitHub
⛨ security enhancement UI/UX
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.