Skip to content

Commit 1a225e6

Browse files
committed
fix: deploy factory with separate implementations to avoid initcode size limit
- Update AgentRegistryFactory constructor to accept pre-deployed implementation addresses - Modify deployment scripts to deploy implementations separately before factory - This avoids 'max initcode size exceeded' errors when deploying the factory
1 parent 6301839 commit 1a225e6

2 files changed

Lines changed: 68 additions & 31 deletions

File tree

script/DeployAgentRegistry.s.sol

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ contract DeployAgentRegistryWithRoles is Script {
9090
/**
9191
* @title DeployAgentRegistryFactory
9292
* @dev Deployment script for AgentRegistryFactory contract (EIP-1167 minimal clones)
93+
* Deploys implementations separately to avoid initcode size limits
9394
*
9495
* Usage:
9596
* forge script script/DeployAgentRegistry.s.sol:DeployAgentRegistryFactory --rpc-url $SEPOLIA_RPC_URL --broadcast --verify
@@ -99,29 +100,49 @@ contract DeployAgentRegistryWithRoles is Script {
99100
* - ETHERSCAN_API_KEY: API key for contract verification (optional)
100101
*/
101102
contract DeployAgentRegistryFactory is Script {
102-
function run() external returns (AgentRegistryFactory factory) {
103+
function run() external returns (AgentRegistryFactory factory, address registryImpl, address registrarImpl) {
103104
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
104105
address deployer = vm.addr(deployerPrivateKey);
105106

106-
console.log("Deploying AgentRegistryFactory...");
107+
console.log("Deploying AgentRegistryFactory with separate implementations...");
107108
console.log("Deployer address:", deployer);
108109

109110
vm.startBroadcast(deployerPrivateKey);
110111

111-
factory = new AgentRegistryFactory();
112+
// Deploy implementations separately to avoid initcode size limits
113+
console.log("Deploying AgentRegistry implementation...");
114+
AgentRegistry registryImplContract = new AgentRegistry();
115+
registryImpl = address(registryImplContract);
116+
console.log("Registry Implementation deployed at:", registryImpl);
117+
118+
console.log("Deploying AgentRegistrar implementation...");
119+
// Deploy registrar implementation with dummy values (will be overwritten on clone init)
120+
AgentRegistrar registrarImplContract = new AgentRegistrar(
121+
AgentRegistry(registryImpl),
122+
0,
123+
0,
124+
deployer
125+
);
126+
registrarImpl = address(registrarImplContract);
127+
console.log("Registrar Implementation deployed at:", registrarImpl);
128+
129+
console.log("Deploying AgentRegistryFactory...");
130+
factory = new AgentRegistryFactory(registryImpl, registrarImpl);
112131

113132
vm.stopBroadcast();
114133

115-
console.log("AgentRegistryFactory deployed at:", address(factory));
116-
console.log("Registry Implementation:", factory.registryImplementation());
117-
console.log("Registrar Implementation:", factory.registrarImplementation());
134+
console.log("");
135+
console.log("=== Deployment Summary ===");
136+
console.log("AgentRegistryFactory:", address(factory));
137+
console.log("Registry Implementation:", registryImpl);
138+
console.log("Registrar Implementation:", registrarImpl);
118139
console.log("");
119140
console.log("To deploy registry + registrar:");
120141
console.log(" factory.deploy(admin, mintPrice, maxSupply)");
121142
console.log("To deploy registry only:");
122143
console.log(" factory.deployRegistry(admin)");
123144

124-
return factory;
145+
return (factory, registryImpl, registrarImpl);
125146
}
126147
}
127148

@@ -152,8 +173,17 @@ contract DeployRegistryAndRegistrar is Script {
152173

153174
vm.startBroadcast(deployerPrivateKey);
154175

176+
// Deploy implementations separately to avoid initcode size limits
177+
AgentRegistry registryImpl = new AgentRegistry();
178+
AgentRegistrar registrarImpl = new AgentRegistrar(
179+
registryImpl,
180+
0,
181+
0,
182+
deployer
183+
);
184+
155185
// Deploy factory
156-
factory = new AgentRegistryFactory();
186+
factory = new AgentRegistryFactory(address(registryImpl), address(registrarImpl));
157187

158188
// Deploy registry + registrar pair
159189
(registry, registrar) = factory.deploy(deployer, mintPrice, maxSupply);
@@ -199,8 +229,17 @@ contract DeployRegistryOnly is Script {
199229

200230
vm.startBroadcast(deployerPrivateKey);
201231

232+
// Deploy implementations separately to avoid initcode size limits
233+
AgentRegistry registryImpl = new AgentRegistry();
234+
AgentRegistrar registrarImpl = new AgentRegistrar(
235+
registryImpl,
236+
0,
237+
0,
238+
deployer
239+
);
240+
202241
// Deploy factory
203-
factory = new AgentRegistryFactory();
242+
factory = new AgentRegistryFactory(address(registryImpl), address(registrarImpl));
204243

205244
// Deploy registry only
206245
registry = factory.deploy(deployer);

src/AgentRegistryFactory.sol

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ contract AgentRegistryFactory {
2222
/// @notice Emitted when a new AgentRegistrar clone is deployed
2323
/// @param registrar The address of the newly deployed registrar clone
2424
/// @param registry The registry the registrar mints to
25-
/// @param owner The owner of the registrar
26-
event RegistrarDeployed(address indexed registrar, address indexed registry, address indexed owner);
25+
/// @param admin The admin of the registrar (receives ADMIN_ROLE, DEFAULT_ADMIN_ROLE, and MINTER_ROLE)
26+
event RegistrarDeployed(address indexed registrar, address indexed registry, address indexed admin);
2727

2828
/// @notice Emitted when both registry and registrar are deployed together
2929
/// @param registry The address of the registry
3030
/// @param registrar The address of the registrar
31-
/// @param admin The admin/owner address
31+
/// @param admin The admin address (receives all roles in both contracts)
3232
event RegistryAndRegistrarDeployed(address indexed registry, address indexed registrar, address indexed admin);
3333

3434
/* --- State Variables --- */
@@ -56,17 +56,15 @@ contract AgentRegistryFactory {
5656

5757
/* --- Constructor --- */
5858

59-
/// @notice Deploy the factory with new implementation contracts
60-
/// @dev Creates AgentRegistry and AgentRegistrar implementations for cloning
61-
constructor() {
62-
registryImplementation = address(new AgentRegistry());
63-
// Deploy registrar implementation with dummy values (will be overwritten on clone init)
64-
registrarImplementation = address(new AgentRegistrar(
65-
AgentRegistry(registryImplementation),
66-
0,
67-
0,
68-
address(this)
69-
));
59+
/// @notice Deploy the factory with pre-deployed implementation contracts
60+
/// @param _registryImplementation The address of the AgentRegistry implementation
61+
/// @param _registrarImplementation The address of the AgentRegistrar implementation
62+
/// @dev Deploy implementations separately first to avoid "max initcode size exceeded" errors
63+
constructor(address _registryImplementation, address _registrarImplementation) {
64+
require(_registryImplementation != address(0), "Invalid registry implementation");
65+
require(_registrarImplementation != address(0), "Invalid registrar implementation");
66+
registryImplementation = _registryImplementation;
67+
registrarImplementation = _registrarImplementation;
7068
}
7169

7270
/* --- Registry Deployment --- */
@@ -165,27 +163,27 @@ contract AgentRegistryFactory {
165163
/// @param registry The AgentRegistry to mint to
166164
/// @param mintPrice Price per mint in wei (0 = free)
167165
/// @param maxSupply Maximum supply (0 = unlimited)
168-
/// @param owner Owner of the registrar
166+
/// @param admin Admin of the registrar (receives ADMIN_ROLE, DEFAULT_ADMIN_ROLE, and MINTER_ROLE)
169167
/// @return registrar The address of the newly deployed registrar
170168
function deployRegistrar(
171169
AgentRegistry registry,
172170
uint256 mintPrice,
173171
uint256 maxSupply,
174-
address owner
172+
address admin
175173
) external returns (address registrar) {
176174
registrar = registrarImplementation.clone();
177-
AgentRegistrar(payable(registrar)).initialize(registry, mintPrice, maxSupply, owner);
175+
AgentRegistrar(payable(registrar)).initialize(registry, mintPrice, maxSupply, admin);
178176

179177
deployedRegistrars.push(registrar);
180178
isDeployedRegistrar[registrar] = true;
181179

182-
emit RegistrarDeployed(registrar, address(registry), owner);
180+
emit RegistrarDeployed(registrar, address(registry), admin);
183181
}
184182

185183
/* --- Combined Deployment --- */
186184

187185
/// @notice Deploy both a registry and registrar together
188-
/// @param admin The admin for the registry and owner of the registrar
186+
/// @param admin The admin for the registry and registrar (receives all roles in both contracts)
189187
/// @param mintPrice Price per mint in wei (0 = free)
190188
/// @param maxSupply Maximum supply (0 = unlimited)
191189
/// @return registry The address of the deployed registry
@@ -233,7 +231,7 @@ contract AgentRegistryFactory {
233231
}
234232

235233
/// @notice Deploy both a registry and registrar together with a name
236-
/// @param admin The admin for the registry and owner of the registrar
234+
/// @param admin The admin for the registry and registrar (receives all roles in both contracts)
237235
/// @param mintPrice Price per mint in wei (0 = free)
238236
/// @param maxSupply Maximum supply (0 = unlimited)
239237
/// @param name The name for the registry (stored as ERC-8049 contract metadata)
@@ -286,7 +284,7 @@ contract AgentRegistryFactory {
286284
}
287285

288286
/// @notice Deploy both a registry and registrar with deterministic addresses
289-
/// @param admin The admin for the registry and owner of the registrar
287+
/// @param admin The admin for the registry and registrar (receives all roles in both contracts)
290288
/// @param mintPrice Price per mint in wei (0 = free)
291289
/// @param maxSupply Maximum supply (0 = unlimited)
292290
/// @param registrySalt Salt for registry address
@@ -338,7 +336,7 @@ contract AgentRegistryFactory {
338336
}
339337

340338
/// @notice Deploy both a registry and registrar with deterministic addresses and a name
341-
/// @param admin The admin for the registry and owner of the registrar
339+
/// @param admin The admin for the registry and registrar (receives all roles in both contracts)
342340
/// @param mintPrice Price per mint in wei (0 = free)
343341
/// @param maxSupply Maximum supply (0 = unlimited)
344342
/// @param registrySalt Salt for registry address

0 commit comments

Comments
 (0)