📋 Context
The ChatterPayWalletFactory contract is responsible for deploying and managing wallet proxies. However, several critical parameters are currently hardcoded during deployment and cannot be updated afterward:
entryPoint: Set in constructor, immutable.
paymaster: Set in constructor, stored as a mutable variable but lacks a setter.
router: Set in constructor, immutable.
This creates several limitations:
- 🔒 Inflexibility: If a new version of
Paymaster, Router, or EntryPoint is deployed, the factory cannot redirect newly created wallets to those updated addresses.
- 🧱 Code Coupling: Wallets created after upgrades require redeploying a new factory with new parameters.
- ❌ Operational Overhead: Each factory redeployment causes fragmentation in wallet management and configuration, increasing gas and deployment complexity.
🛠 Strategy
Several strategies were considered to address this:
| Strategy |
Description |
Pros |
Cons |
| A. Add setters in the factory |
Add setEntryPoint(), setPaymaster(), setRouter() functions |
Simple, maintains single factory |
Risk of improper updates |
| B. Move to upgradeable factory |
Make the factory upgradeable (UUPS proxy) |
Full control |
Adds complexity, audit risk |
| C. Use registry pattern |
Central config registry for contracts to query |
Highly modular |
Increased gas cost per wallet creation |
The recommended approach is Strategy A.
🔬 Gas Analysis
The current gas cost of setting these fields during construction is negligible.
After adding setters:
SSTORE: ~20,000 gas per update (executed only once per change).
- No additional runtime cost unless
createProxy() is updated to query these variables dynamically.
✅ Recommended Implementation
Implement individual setters for each configurable field:
function setPaymaster(address _paymaster) external onlyOwner {
if (_paymaster == address(0)) revert ChatterPayWalletFactory__ZeroAddress();
paymaster = _paymaster;
}
function setRouter(address _router) external onlyOwner {
if (_router == address(0)) revert ChatterPayWalletFactory__ZeroAddress();
// optional: emit event
assembly { sstore(router.slot, _router) }
}
function setEntryPoint(address _entryPoint) external onlyOwner {
if (_entryPoint == address(0)) revert ChatterPayWalletFactory__ZeroAddress();
assembly { sstore(entryPoint.slot, _entryPoint) }
}
Note: Since entryPoint and router are currently declared as immutable, they must be changed to public mutable variables in order to support this.
address public entryPoint;
address public router;
📌 Auditor Notes
- 🔐 Restrict all setters with
onlyOwner
- 📣 Emit events on configuration changes to support off-chain indexers
- 🧪 Add tests to ensure wallets created after updates use the new configuration
- 🪵 Consider logging
configVersion or similar tracking mechanism
🧠 Final Thoughts
Allowing the factory to update paymaster, router, and entryPoint enables operational agility without compromising on safety (when gated by onlyOwner). This makes onboarding to new infra components easier and keeps wallet creation logic centralized.
📋 Context
The
ChatterPayWalletFactorycontract is responsible for deploying and managing wallet proxies. However, several critical parameters are currently hardcoded during deployment and cannot be updated afterward:entryPoint: Set in constructor, immutable.paymaster: Set in constructor, stored as a mutable variable but lacks a setter.router: Set in constructor, immutable.This creates several limitations:
Paymaster,Router, orEntryPointis deployed, the factory cannot redirect newly created wallets to those updated addresses.🛠 Strategy
Several strategies were considered to address this:
setEntryPoint(),setPaymaster(),setRouter()functionsThe recommended approach is Strategy A.
🔬 Gas Analysis
The current gas cost of setting these fields during construction is negligible.
After adding setters:
SSTORE: ~20,000 gas per update (executed only once per change).createProxy()is updated to query these variables dynamically.✅ Recommended Implementation
Implement individual setters for each configurable field:
Note: Since
entryPointandrouterare currently declared asimmutable, they must be changed topublicmutable variables in order to support this.📌 Auditor Notes
onlyOwnerconfigVersionor similar tracking mechanism🧠 Final Thoughts
Allowing the factory to update
paymaster,router, andentryPointenables operational agility without compromising on safety (when gated byonlyOwner). This makes onboarding to new infra components easier and keeps wallet creation logic centralized.