🔐 MULTISIG OWNER SETUP
✅ UPDATED FOR MULTISIG OWNERSHIP
The StrategyDeploymentBatcher now accepts a custom owner parameter, allowing you to use your multisig wallet as the owner of all deployed strategies!
🎯 YOUR MULTISIG:
0x7d429eCbdcE5ff516D6e0a93299cbBa97203f2d3
📋 WHAT CHANGED:
Before:
function batchDeployStrategies(
address underlyingToken,
address quoteToken,
address creatorVault,
address _ajnaFactory,
uint24 v3FeeTier,
uint160 initialSqrtPriceX96
) external
Owner was: msg.sender (the caller)
After:
function batchDeployStrategies(
address underlyingToken,
address quoteToken,
address creatorVault,
address _ajnaFactory,
uint24 v3FeeTier,
uint160 initialSqrtPriceX96,
address owner // ⭐ NEW PARAMETER
) external
Owner is: The specified owner address (your multisig)
🚀 HOW TO DEPLOY:
Transaction 1: Deploy All Strategies
DeploymentResult memory result = batcher.batchDeployStrategies(
creatorToken, // CREATOR token
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913, // USDC on Base
creatorVault, // Your CreatorOVault
ajnaFactory, // Ajna factory (or address(0))
3000, // 0.3% fee tier
sqrtPriceX96, // Initial price
0x7d429eCbdcE5ff516D6e0a93299cbBa97203f2d3 // ⭐ YOUR MULTISIG
);
Result:
- ✅ CharmAlphaVault deployed (
pendingGovernance = your multisig) - ✅ No separate CharmAlphaStrategy deployed (rebalance is embedded in CharmAlphaVaultDeploy)
- ✅ CreatorCharmStrategyV2 deployed (
owner = your multisig) - ✅ AjnaStrategy deployed (
owner = your multisig)
Transaction 2: Accept Governance (FROM MULTISIG)
Important: This transaction MUST be sent from your multisig wallet!
CharmAlphaVault(result.charmVault).acceptGovernance();
After this:
- ✅ Your multisig is now the full owner of CharmAlphaVault
- ✅ You can adjust fees, caps, strategy, etc.
🔐 OWNERSHIP SUMMARY:
| Contract | Owner | Type |
|---|---|---|
| CharmAlphaVault | Your Multisig | Governance (after accepting) |
| CharmAlphaStrategy | ❌ Not deployed | Embedded |
| CreatorCharmStrategyV2 | Your Multisig | Owner |
| AjnaStrategy | Your Multisig | Owner |
🛡️ WHY MULTISIG IS BETTER:
| Aspect | EOA | Multisig |
|---|---|---|
| Security | ❌ Single point of failure | ✅ Multiple signers required |
| Key Loss | ❌ If lost, funds gone forever | ✅ Other signers can recover |
| Compromise | ❌ One key = full access | ✅ Attacker needs multiple keys |
| Transparency | ❌ No visibility | ✅ All signers see transactions |
| Accountability | ❌ No audit trail | ✅ Who signed what is recorded |
Your multisig (0x7d429eCbdcE5ff516D6e0a93299cbBa97203f2d3) is the RIGHT choice! 🎉
📊 COMPLETE DEPLOYMENT FLOW:
┌─────────────────────────────────────────────────────┐
│ Step 1: ANYONE calls batchDeployStrategies() │
│ (Can be EOA, can be multisig, can be different) │
└─────────────────────────────────────────────────────┘
↓
┌────────────────────────────┐
│ Contracts Deployed: │
│ - CharmAlphaVault │
│ - (no separate CharmAlphaStrategy) │
│ - CreatorCharmStrategyV2 │
│ - AjnaStrategy │
└────────────────────────────┘
↓
┌────────────────────────────┐
│ Ownership Status: │
│ pendingGovernance = 0x7d..│
│ keeper = 0x7d... │
│ owner = 0x7d... │
└────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ Step 2: MULTISIG calls acceptGovernance() │
│ Must be called by: 0x7d429eCbdcE5ff516D6e0a93299cbBa97203f2d3 │
└─────────────────────────────────────────────────────┘
↓
┌────────────────────────────┐
│ ✅ MULTISIG NOW OWNS ALL │
└────────────────────────────┘
⚠️ IMPORTANT NOTES:
1. Accept Governance MUST Come From Multisig
// ❌ WRONG - Called from different address
EOA.call(charmVault.acceptGovernance()) // Will REVERT
// ✅ CORRECT - Called from multisig
Multisig(0x7d429eCbdcE5ff516D6e0a93299cbBa97203f2d3).call(
charmVault.acceptGovernance()
)
2. You Don't Need to Deploy From Multisig
- Anyone can call
batchDeployStrategies()(costs gas) - The
ownerparameter determines ownership - Multisig only needs to accept governance (cheap transaction)
3. Ownership is Immediate for Most Contracts
- CreatorCharmStrategyV2: Owned immediately ✅
- AjnaStrategy: Owned immediately ✅
- CharmAlphaStrategy: Not deployed (embedded) ✅
- CharmAlphaVault: Requires acceptance ⚠️
🎯 CHECKLIST:
- 1. Call
batchDeployStrategies()with multisig address asownerparameter - 2. Note the returned
result.charmVaultaddress - 3. From your multisig, call
CharmAlphaVault(address).acceptGovernance() - 4. Verify ownership by calling
CharmAlphaVault.governance()→ should return your multisig - 5. Test a governance function (like
setProtocolFee()) from multisig ✅ - 6. Add strategies to your CreatorOVault
- 7. Start accepting deposits!
💡 EXAMPLE DEPLOYMENT SCRIPT:
// Step 1: Deploy (can be from any address)
const batcher = new ethers.Contract(batcherAddress, batcherABI, signer);
const tx = await batcher.batchDeployStrategies(
creatorToken,
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
vaultAddress,
ajnaFactory,
3000,
sqrtPriceX96,
"0x7d429eCbdcE5ff516D6e0a93299cbBa97203f2d3" // Your multisig
);
const receipt = await tx.wait();
// Parse event to get addresses
const event = receipt.events.find(e => e.event === "StrategiesDeployed");
const charmVaultAddress = event.args.result.charmVault;
// Step 2: Accept from multisig (using Safe SDK or direct call)
const charmVault = new ethers.Contract(
charmVaultAddress,
charmVaultABI,
multisigSigner // ⚠️ Must be multisig signer
);
await charmVault.acceptGovernance();
console.log("✅ Multisig now owns CharmAlphaVault!");
🔐 SECURITY BEST PRACTICES:
- ✅ Use multisig for ownership (you're doing this!)
- ✅ Require multiple signers (2-of-3 or 3-of-5 recommended)
- ✅ Keep signer keys separate (different hardware wallets)
- ✅ Test on testnet first (Base Sepolia)
- ✅ Verify all contract addresses before accepting governance
- ✅ Document all transactions for audit trail
🎉 YOU'RE ALL SET!
Your multisig 0x7d429eCbdcE5ff516D6e0a93299cbBa97203f2d3 will own all deployed strategies!
This is much more secure than using an EOA. Great decision! 🛡️