xiaohongshu
xiaohongshu
erc4337-privacy-wallet
Privacy-preserving ERC-4337 wallet development for vehicle identity and sensitive data protection. Use when implementing ERC-4337 account abstraction wallets that handle sensitive information (vehicle license plates, biometric data, personal IDs) requiring on-chain privacy. Triggers on requests l...
Full skill instructions
This skill provides comprehensive support for developing ERC-4337 compliant Account Abstraction wallets with privacy-preserving features, specifically designed for vehicle identity and other sensitive data use cases. It combines smart contract templates, testing frameworks, privacy validation tools, and security best practices to enable the secure implementation of wallets that protect user privacy while maintaining on-chain functionality.
Key Capabilities:
Invoke this skill when you encounter requests involving:
Ask the user these key questions:
# Copy contract templates
cp -r assets/contracts/* ./contracts/
# Install dependencies
cd contracts
npm install
# Compile contracts
npm run compile
For vehicle-based wallets:
// Off-chain: Compute vehicle commitment
const plateNumber = "ABC-1234";
const userSalt = ethers.id("user-secret-entropy");
const commitment = ethers.keccak256(
ethers.solidityPacked(["string", "bytes32"], [plateNumber, userSalt])
);
// Deploy account with commitment
const account = await factory.createAccount(
ownerAddress,
commitment,
12345 // deployment salt
);
For biometric/other sensitive data:
// Replace plateNumber with your sensitive data
const biometricHash = computeHash(biometricData);
const commitment = ethers.keccak256(
ethers.solidityPacked(["bytes32", "bytes32"], [biometricHash, userSalt])
);
# Validate that contracts don't leak sensitive data
python scripts/validate_privacy.py contracts/PrivacyProtectedAccount.sol
# Run comprehensive test suite
npm test
# Run specific test file
npx hardhat test tests/PrivacyProtectedAccount.test.ts
The main account contract that implements ERC-4337's IAccount interface with privacy features.
Key Features:
Usage:
// Deploy via factory
const account = await factory.createAccount(owner, vehicleCommitment, salt);
// Verify ownership without revealing data
const isValid = await account.verifyVehicleOwnership(plateNumber, userSalt);
// Execute transaction
await account.execute(targetAddress, value, calldata);
Privacy Guarantee:
bytes32 hashFactory contract for deploying PrivacyProtectedAccount instances with deterministic addresses.
Key Features:
Usage:
// Compute address before deployment
const predictedAddress = await factory.getAddress(owner, commitment, salt);
// Deploy account
const account = await factory.createAccount(owner, commitment, salt);
// Address matches prediction
assert(accountAddress === predictedAddress);
Use Cases:
Optional registry contract for managing vehicle-to-wallet mappings with privacy.
Key Features:
Usage:
// Register vehicle with commitment only
await registry.registerVehicle(commitment, walletAddress, metadataHash);
// Verify registration (authorized only)
const isRegistered = await registry.verifyVehicleRegistration(commitment);
// Update commitment (ownership transfer)
await registry.updateVehicleCommitment(oldCommitment, newCommitment);
Determine what needs privacy protection:
Example - Vehicle Wallet:
Sensitive: License plate number
Public: Wallet address, transaction history
Commitment: keccak256(plateNumber + salt)
Example - Biometric Wallet:
Sensitive: Fingerprint hash
Public: Wallet address
Commitment: keccak256(fingerprintHash + salt)
CRITICAL: Never pass raw sensitive data to blockchain functions.
// Frontend/Backend - OFF-CHAIN computation
import { ethers } from 'ethers';
function generateCommitment(sensitiveData, userSecret) {
// Generate cryptographically secure salt
const salt = ethers.keccak256(
ethers.solidityPacked(
['string', 'uint256', 'address'],
[userSecret, Date.now(), userAddress]
)
);
// Compute commitment
const commitment = ethers.keccak256(
ethers.solidityPacked(['string', 'bytes32'], [sensitiveData, salt])
);
return { commitment, salt };
}
// Usage
const { commitment, salt } = generateCommitment(licensePlate, userSecret);
// Store salt securely off-chain!
// Send only commitment to blockchain
// Connect to factory
const factory = await ethers.getContractAt('AccountFactory', factoryAddress);
// Optional: Predict address first
const predictedAddress = await factory.getAddress(
ownerAddress,
commitment,
deploymentSalt
);
console.log('Account will be deployed at:', predictedAddress);
// Deploy account
const tx = await factory.createAccount(ownerAddress, commitment, deploymentSalt);
await tx.wait();
console.log('Account deployed at:', predictedAddress);
import { ethers } from 'ethers';
// Build UserOperation
const userOp = {
sender: accountAddress,
nonce: await account.getNonce(),
initCode: '0x', // Empty if account exists
callData: account.interface.encodeFunctionData('execute', [
targetAddress,
value,
data
]),
accountGasLimits: ethers.solidityPacked(
['uint128', 'uint128'],
[verificationGasLimit, callGasLimit]
),
preVerificationGas,
gasFees: ethers.solidityPacked(
['uint128', 'uint128'],
[maxPriorityFeePerGas, maxFeePerGas]
),
paymasterAndData: '0x', // Or paymaster address + data
signature: '0x' // Will be filled after signing
};
// Sign UserOperation
const userOpHash = await account.getUserOpHash(userOp);
const signature = await owner.signMessage(ethers.getBytes(userOpHash));
userOp.signature = signature;
// Submit to bundler
await bundler.sendUserOperation(userOp);
# Run automated privacy validation
python scripts/validate_privacy.py contracts/YourContract.sol
# Expected output:
# ✅ PRIVACY VALIDATION PASSED
# No privacy violations detected.
// Off-chain
const commitment = keccak256(abi.encodePacked(sensitiveData, salt));
// On-chain
bytes32 public dataCommitment;
function initialize(bytes32 _commitment) external {
dataCommitment = _commitment;
}
function verify(string memory data, bytes32 salt) external view returns (bool) {
return keccak256(abi.encodePacked(data, salt)) == dataCommitment;
}
// For vehicles with multiple attributes
struct VehicleData {
string plateNumber;
string model;
uint256 year;
}
// Off-chain
const commitment = keccak256(abi.encode(
vehicleData.plateNumber,
vehicleData.model,
vehicleData.year,
salt
));
For advanced privacy (see references/privacy-patterns.md for full examples):
// Verify ZK proof instead of revealing data
function _validateSignature(
PackedUserOperation calldata userOp,
bytes32 userOpHash
) internal override returns (uint256) {
(bytes memory proof, bytes memory publicInputs) =
abi.decode(userOp.signature, (bytes, bytes));
require(zkVerifier.verify(proof, publicInputs), "Invalid proof");
return SIG_VALIDATION_SUCCESS;
}
describe("Privacy Protection", () => {
it("should not store raw sensitive data", async () => {
// Verify storage doesn't contain plate number
for (let i = 0; i < 20; i++) {
const storage = await ethers.provider.getStorage(account.address, i);
expect(storage).to.not.include(ethers.hexlify(ethers.toUtf8Bytes(plateNumber)));
}
});
it("should verify with correct preimage", async () => {
const isValid = await account.verifyVehicleOwnership(plateNumber, salt);
expect(isValid).to.be.true;
});
it("should reject wrong preimage", async () => {
const isValid = await account.verifyVehicleOwnership("WRONG-PLATE", salt);
expect(isValid).to.be.false;
});
});
describe("UserOperation Validation", () => {
it("should validate correct signature", async () => {
const userOp = buildUserOp({ sender: account.address });
const userOpHash = await entryPoint.getUserOpHash(userOp);
userOp.signature = await owner.signMessage(ethers.getBytes(userOpHash));
await expect(entryPoint.handleOps([userOp], bundler.address))
.to.not.be.reverted;
});
});
Before deploying to mainnet, verify:
python scripts/validate_privacy.pynpm testview or pureSee references/security-checklist.md for complete checklist.
// NEVER DO THIS
contract BadExample {
string public licensePlate; // Publicly visible!
}
// DO THIS
contract GoodExample {
bytes32 public vehicleCommitment; // Only hash stored
}
// WEAK - predictable
bytes32 salt = bytes32(block.timestamp);
// STRONG - unique per user with high entropy
bytes32 salt = keccak256(abi.encodePacked(
userSecret,
block.timestamp,
block.prevrandao,
msg.sender
));
// NEVER DO THIS
event VehicleRegistered(string plateNumber);
// DO THIS
event VehicleRegistered(bytes32 indexed commitment);
For zero-knowledge proof integration, see references/privacy-patterns.md section on ZK proofs.
High-level flow:
_validateSignature()# Deploy to multiple networks with same addresses
npx hardhat run scripts/deploy.ts --network sepolia
npx hardhat run scripts/deploy.ts --network polygonAmoy
# Addresses match due to CREATE2 determinism
// Add paymaster to UserOperation
userOp.paymasterAndData = ethers.solidityPacked(
['address', 'bytes'],
[paymasterAddress, paymasterData]
);
// User doesn't pay gas - paymaster sponsors it
assets/contracts/: Production-ready contract templates
PrivacyProtectedAccount.sol - Main account contractAccountFactory.sol - Deterministic factoryVehicleRegistry.sol - Optional registrypackage.json, hardhat.config.ts - Project setupassets/tests/: Comprehensive test suites
scripts/validate_privacy.py: Automated privacy validation tool
references/: In-depth documentation
erc4337-architecture.md - ERC-4337 deep diveprivacy-patterns.md - Privacy implementation patternssecurity-checklist.md - Comprehensive security guideIssue: Gas estimation fails
Solution: Ensure account has sufficient deposit in EntryPoint
await account.addDeposit({ value: ethers.parseEther("0.1") });
Issue: Signature validation fails
Solution: Check that userOpHash is computed correctly
const userOpHash = await entryPoint.getUserOpHash(userOp);
Issue: Privacy validation fails
Solution: Review reported violations and fix
- Remove string storage for sensitive data
- Make verification functions view/pure
- Use commitments instead of raw data
references/ for detailed documentationxiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience