# 3.3 Error Prevention & Recovery
Users must be protected from costly mistakes.
## Success Criteria
### 3.3.1 Cross-Network Address Validation (Level A)
**Requirement**: Addresses must be validated for the current network. Attempts to send to addresses on different networks must be blocked with clear explanations.
**Intent**: Sending to wrong-network addresses loses funds permanently. Validation prevents this.
**Benefits**:
- **All users**: Prevent irreversible losses
- **New users**: Protected from common mistake
- **Cognitive disabilities**: Error prevention over recovery
**Techniques**:
```tsx
function validateAddress(address: string, network: Network) {
const validationResult = {
isValid: false,
error: null,
warning: null,
};
// Check address format
if (!isValidAddress(address)) {
validationResult.error = 'Invalid address format';
return validationResult;
}
// Check network compatibility
if (isContractAddress(address)) {
const deployedNetworks = getContractNetworks(address);
if (!deployedNetworks.includes(network.chainId)) {
validationResult.error =
`This appears to be a contract address that doesn't exist on ${network.name}. ` +
`Sending here would result in lost funds.`;
return validationResult;
}
}
// Check for common mistakes
if (isKnownExchange(address) && network.chainId !== 1) {
validationResult.warning =
`This looks like an exchange address. Make sure ${network.name} deposits are supported.`;
}
validationResult.isValid = true;
return validationResult;
}
<AddressInput>
<input
type="text"
value={address}
onChange={handleAddressChange}
aria-invalid={!!validation.error}
aria-describedby="address-error"
/>
{validation.error && (
<div id="address-error" role="alert" className="error">
<ErrorIcon aria-hidden="true" />
{validation.error}
</div>
)}
{validation.warning && (
<div role="status" className="warning">
<WarningIcon aria-hidden="true" />
{validation.warning}
</div>
)}
</AddressInput>
```
**Failures**:
- No address validation
- Validation only checks format
- Error not communicated to screen readers
---
### 3.3.2 Large Transaction Confirmation (Level A)
**Requirement**: Transactions above user-defined thresholds must require explicit secondary confirmation with amount displayed prominently.
**Intent**: Large transactions deserve extra attention. Confirmation prevents accidental large sends.
**Benefits**:
- **All users**: Catch accidental extra zeros
- **Cognitive disabilities**: Double-check opportunity
- **Security**: Reduced fat-finger risk
**Techniques**:
```tsx
const LARGE_TX_THRESHOLD = 1000; // $1000 USD equivalent
<TransactionConfirmation amount={amount}>
{amount > LARGE_TX_THRESHOLD && (
<LargeTransactionWarning>
<div role="alertdialog" aria-labelledby="large-tx-title">
<h2 id="large-tx-title">Large Transaction</h2>
<p className="amount-highlight">
You are about to send <strong>${formatCurrency(amount)}</strong>
</p>
<p>
This is above your large transaction threshold (${LARGE_TX_THRESHOLD}).
Please confirm this is correct.
</p>
<label>
<input
type="checkbox"
checked={confirmed}
onChange={setConfirmed}
required
/>
I confirm this amount is correct
</label>
<div className="actions">
<button onClick={cancel}>Cancel</button>
<button
onClick={proceed}
disabled={!confirmed}
>
Confirm ${formatCurrency(amount)}
</button>
</div>
</div>
</LargeTransactionWarning>
)}
</TransactionConfirmation>
// User settings for threshold
<Settings>
<label>
Large transaction warning threshold:
<input
type="number"
value={threshold}
onChange={updateThreshold}
min={0}
aria-describedby="threshold-help"
/>
</label>
<p id="threshold-help">
You'll be asked to confirm transactions above this amount.
</p>
</Settings>
```
**Failures**:
- No large transaction confirmation
- Threshold cannot be customized
- Confirmation is single-click
---
### 3.3.3 Simulation Failure Blocking (Level AA)
**Requirement**: When transaction simulations fail or predict errors, the transaction must be blocked from submission with clear explanation of the failure.
**Intent**: Simulations predict failure. Blocking prevents wasted gas and failed transactions.
**Benefits**:
- **All users**: Prevent failed transactions
- **Cost savings**: Don't pay gas for known failures
- **Debugging**: Clear failure explanation
**Techniques**:
```tsx
async function handleTransaction(tx: Transaction) {
// Simulate first
const simulation = await simulateTransaction(tx);
if (!simulation.success) {
return (
<SimulationFailure>
<div role="alert">
<h2>Transaction Would Fail</h2>
<p>
We simulated this transaction and it would fail with the
following error:
</p>
<code className="error-message">
{simulation.errorMessage}
</code>
<div className="explanation">
<h3>What this means:</h3>
<p>{getHumanReadableError(simulation.errorCode)}</p>
</div>
<div className="suggestions">
<h3>How to fix:</h3>
<ul>
{simulation.suggestions.map(suggestion => (
<li key={suggestion.id}>{suggestion.text}</li>
))}
</ul>
</div>
<button onClick={close}>Close</button>
{/* Optional: allow override for advanced users */}
<details>
<summary>Advanced: Submit anyway</summary>
<p>
This transaction is predicted to fail. Only proceed if
you understand why and believe the simulation is incorrect.
</p>
<button
onClick={forceSubmit}
className="dangerous"
>
Submit Anyway (Not Recommended)
</button>
</details>
</div>
</SimulationFailure>
);
}
// Proceed with transaction
return submitTransaction(tx);
}
```
**Failures**:
- Simulation failures don't block submission
- Error messages are technical only
- No suggestions for resolution
---
### 3.3.4 Gas Reserve Warning (Level AA)
**Requirement**: When using "Max" or spending all of a gas token, users must be warned about leaving insufficient reserves for future transactions.
**Intent**: Spending all ETH leaves users unable to transact. Warning prevents this trap.
**Benefits**:
- **New users**: Understand gas requirements
- **All users**: Maintain transaction ability
- **Cost savings**: Avoid needing to bridge/buy gas
**Techniques**:
```tsx
<MaxAmountButton onClick={handleMax}>
{gasTokenBalance - MINIMUM_RESERVE < amount && (
<div role="alert" className="warning">
<WarningIcon aria-hidden="true" />
<p>
Using this amount will leave less than {MINIMUM_RESERVE} {gasToken}
for network fees. You may not be able to make future transactions.
</p>
<p>
Recommended: Keep at least {RECOMMENDED_RESERVE} {gasToken} for fees.
</p>
<div className="options">
<button onClick={() => setAmount(maxWithReserve)}>
Use max with reserve ({maxWithReserve} {token})
</button>
<button onClick={() => setAmount(absoluteMax)}>
Use absolute max ({absoluteMax} {token})
</button>
</div>
</div>
)}
</MaxAmountButton>
```
**Failures**:
- Max uses 100% with no warning
- No suggested reserve amount
- Warning not screen reader accessible
---
### 3.3.5 Pattern-Based Anomaly Detection (Level AAA)
**Requirement**: Applications detect unusual transaction patterns based on user history and warn before potentially erroneous transactions.
**Intent**: Machine learning from history can catch mistakes humans miss.
**Benefits**:
- **All users**: Personalized error detection
- **Cognitive disabilities**: System catches oversights
- **Security**: Detect compromised accounts
**Techniques**:
```tsx
const anomalyChecks = [
{
check: (tx) => tx.amount > user.avgTransaction * 10,
message: "This transaction is 10x larger than your usual amount",
},
{
check: (tx) => !user.interactedWith.includes(tx.to),
message: "You've never sent to this address before",
},
{
check: (tx) => tx.gasPrice > network.avgGas * 5,
message: "Gas price is unusually high right now",
},
{
check: (tx) => isContractCall(tx) && isNewContract(tx.to),
message: "This contract was deployed in the last 24 hours",
},
];
<TransactionReview>
{anomalies.length > 0 && (
<AnomalyWarnings>
<h3>Unusual Activity Detected</h3>
<ul>
{anomalies.map(anomaly => (
<li key={anomaly.id} role="alert">
{anomaly.message}
</li>
))}
</ul>
<p>
These patterns are unusual for your account. Please verify
this transaction is intentional.
</p>
</AnomalyWarnings>
)}
</TransactionReview>
```
**Failures**:
- No pattern analysis
- Warnings for every transaction (alert fatigue)
- No user control over sensitivity
---
## Testing Checklist
- [ ] Wrong-network addresses are blocked
- [ ] Error explains the specific problem
- [ ] Large transactions require confirmation
- [ ] Threshold is customizable
- [ ] Simulation failures block submission
- [ ] Human-readable error explanations
- [ ] Max warns about gas reserves
- [ ] Reserve suggestion provided
- [ ] Anomaly detection for unusual patterns
## Related Components
- [AddressInput.tsx](../../components/AddressInput.tsx)
- [LargeTransactionConfirm.tsx](../../components/LargeTransactionConfirm.tsx)
- [SimulationResult.tsx](../../components/SimulationResult.tsx)