-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
282 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.12; | ||
|
||
import "forge-std/Script.sol"; | ||
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; | ||
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; | ||
|
||
import {AVSCreator, EmptyContract} from "../src/core/AVSCreator.sol"; | ||
import {IndexRegistry} from "eigenlayer-middleware/IndexRegistry.sol"; | ||
import {StakeRegistry} from "eigenlayer-middleware/StakeRegistry.sol"; | ||
import {BLSApkRegistry} from "eigenlayer-middleware/BLSApkRegistry.sol"; | ||
import {RegistryCoordinator} from "eigenlayer-middleware/RegistryCoordinator.sol"; | ||
import {MachServiceManager} from "../src/core/MachServiceManager.sol"; | ||
|
||
// DELEGATION_MANAGER=$DELEGATION_MANAGER AVS_DIRECTORY=$AVS_DIRECTORY forge script ./script/AVSCreatorDeployer.s.sol \ | ||
// --private-key $PK \ | ||
// --rpc-url $URL \ | ||
// --etherscan-api-key $API_KEY \ | ||
// --broadcast -vvvv --slow --verify | ||
contract AVSCreatorDeployer is Script { | ||
function run() external { | ||
vm.startBroadcast(); | ||
|
||
// Deploy AVSCreator | ||
address delegationManager = vm.envAddress("DELEGATION_MANAGER"); | ||
address avsDirectory = vm.envAddress("AVS_DIRECTORY"); | ||
|
||
AVSCreator creator = new AVSCreator(delegationManager, avsDirectory); | ||
|
||
// Set the bytecodes | ||
creator.setIndexRegistryBytecode(type(IndexRegistry).creationCode); | ||
creator.setStakeRegistryBytecode(type(StakeRegistry).creationCode); | ||
creator.setApkRegistryBytecode(type(BLSApkRegistry).creationCode); | ||
creator.setRegistryCoordinatorBytecode(type(RegistryCoordinator).creationCode); | ||
creator.setServiceManagerBytecode(type(MachServiceManager).creationCode); | ||
|
||
( | ||
address indexRegistryProxy, | ||
address stakeRegistryProxy, | ||
address apkRegistryProxy, | ||
address registryCoordinatorProxy, | ||
address serviceManagerProxy, | ||
ProxyAdmin proxyAdmin | ||
) = creator.createAVS(); | ||
creator.createServiceManagerImplementation(registryCoordinatorProxy, stakeRegistryProxy); | ||
|
||
// Stop broadcasting transactions | ||
vm.stopBroadcast(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.12; | ||
|
||
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; | ||
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; | ||
|
||
contract EmptyContract {} | ||
|
||
contract AVSCreator { | ||
error AlreadySet(); | ||
|
||
address public immutable emptyContract; | ||
address public immutable delegationManager; | ||
address public immutable avsDirectory; | ||
|
||
bytes public indexRegistryBytecode; | ||
bytes public stakeRegistryBytecode; | ||
bytes public apkRegistryBytecode; | ||
bytes public registryCoordinatorBytecode; | ||
bytes public serviceManagerBytecode; | ||
|
||
event Created( | ||
address indexRegistryProxy, | ||
address stakeRegistryProxy, | ||
address apkRegistryProxy, | ||
address registryCoordinatorProxy, | ||
address serviceManagerProxy | ||
); | ||
|
||
modifier setOnce(bytes memory bytecode) { | ||
if (bytecode.length != 0) { | ||
revert AlreadySet(); | ||
} | ||
_; | ||
} | ||
|
||
constructor(address delegationManager_, address avsDirectory_) { | ||
delegationManager = delegationManager_; | ||
avsDirectory = avsDirectory_; | ||
emptyContract = address(new EmptyContract()); | ||
} | ||
|
||
function setIndexRegistryBytecode(bytes calldata bytecode) external setOnce(indexRegistryBytecode) { | ||
indexRegistryBytecode = bytecode; | ||
} | ||
|
||
function setStakeRegistryBytecode(bytes calldata bytecode) external setOnce(stakeRegistryBytecode) { | ||
stakeRegistryBytecode = bytecode; | ||
} | ||
|
||
function setApkRegistryBytecode(bytes calldata bytecode) external setOnce(apkRegistryBytecode) { | ||
apkRegistryBytecode = bytecode; | ||
} | ||
|
||
function setRegistryCoordinatorBytecode(bytes calldata bytecode) external setOnce(registryCoordinatorBytecode) { | ||
registryCoordinatorBytecode = bytecode; | ||
} | ||
|
||
function setServiceManagerBytecode(bytes calldata bytecode) external setOnce(serviceManagerBytecode) { | ||
serviceManagerBytecode = bytecode; | ||
} | ||
|
||
function createAVS() external returns (address, address, address, address, address, ProxyAdmin) { | ||
ProxyAdmin proxyAdmin = new ProxyAdmin(); | ||
|
||
// Deploy proxies for each contract | ||
address indexRegistryProxy = address(new TransparentUpgradeableProxy(emptyContract, address(proxyAdmin), "")); | ||
address stakeRegistryProxy = address(new TransparentUpgradeableProxy(emptyContract, address(proxyAdmin), "")); | ||
address apkRegistryProxy = address(new TransparentUpgradeableProxy(emptyContract, address(proxyAdmin), "")); | ||
address registryCoordinatorProxy = | ||
address(new TransparentUpgradeableProxy(emptyContract, address(proxyAdmin), "")); | ||
address serviceManagerProxy = address(new TransparentUpgradeableProxy(emptyContract, address(proxyAdmin), "")); | ||
|
||
// Deploy the actual implementation contracts | ||
address registryCoordinatorImpl = _createImplementation( | ||
abi.encodePacked( | ||
registryCoordinatorBytecode, | ||
abi.encode(serviceManagerProxy, stakeRegistryProxy, apkRegistryProxy, indexRegistryProxy) | ||
) | ||
); | ||
address indexRegistryImpl = | ||
_createImplementation(abi.encodePacked(indexRegistryBytecode, abi.encode(registryCoordinatorProxy))); | ||
|
||
address stakeRegistryImpl = _createImplementation( | ||
abi.encodePacked(stakeRegistryBytecode, abi.encode(registryCoordinatorProxy, delegationManager)) | ||
); | ||
|
||
address apkRegistryImpl = | ||
_createImplementation(abi.encodePacked(apkRegistryBytecode, abi.encode(registryCoordinatorProxy))); | ||
|
||
emit Created( | ||
indexRegistryProxy, stakeRegistryProxy, apkRegistryProxy, registryCoordinatorProxy, serviceManagerProxy | ||
); | ||
|
||
proxyAdmin.upgrade(TransparentUpgradeableProxy(payable(registryCoordinatorProxy)), registryCoordinatorImpl); | ||
proxyAdmin.upgrade(TransparentUpgradeableProxy(payable(indexRegistryProxy)), indexRegistryImpl); | ||
proxyAdmin.upgrade(TransparentUpgradeableProxy(payable(stakeRegistryProxy)), stakeRegistryImpl); | ||
proxyAdmin.upgrade(TransparentUpgradeableProxy(payable(apkRegistryProxy)), apkRegistryImpl); | ||
|
||
proxyAdmin.transferOwnership(msg.sender); | ||
|
||
return ( | ||
indexRegistryProxy, | ||
stakeRegistryProxy, | ||
apkRegistryProxy, | ||
registryCoordinatorProxy, | ||
serviceManagerProxy, | ||
proxyAdmin | ||
); | ||
} | ||
|
||
function createServiceManagerImplementation(address registryCoordinatorProxy_, address stakeRegistryProxy_) | ||
external | ||
returns (address) | ||
{ | ||
address impl = _createImplementation( | ||
abi.encodePacked( | ||
serviceManagerBytecode, abi.encode(avsDirectory, registryCoordinatorProxy_, stakeRegistryProxy_) | ||
) | ||
); | ||
return impl; | ||
} | ||
|
||
function _createImplementation(bytes memory bytecodeWithConstructor) internal returns (address) { | ||
address addr; | ||
assembly { | ||
addr := create(0, add(bytecodeWithConstructor, 0x20), mload(bytecodeWithConstructor)) | ||
if iszero(extcodesize(addr)) { revert(0, 0) } | ||
} | ||
return addr; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.12; | ||
|
||
import "forge-std/Test.sol"; | ||
import "../src/core/AVSCreator.sol"; | ||
import {IndexRegistry} from "eigenlayer-middleware/IndexRegistry.sol"; | ||
import {StakeRegistry} from "eigenlayer-middleware/StakeRegistry.sol"; | ||
import {BLSApkRegistry} from "eigenlayer-middleware/BLSApkRegistry.sol"; | ||
import {RegistryCoordinator} from "eigenlayer-middleware/RegistryCoordinator.sol"; | ||
import {MachServiceManager} from "../src/core/MachServiceManager.sol"; | ||
|
||
contract AVSCreatorTest is Test { | ||
AVSCreator public avsCreator; | ||
address delegationManager = address(0x1); | ||
address avsDirectory = address(0x2); | ||
|
||
function setUp() public { | ||
avsCreator = new AVSCreator(delegationManager, avsDirectory); | ||
} | ||
|
||
// Test initial contract setup | ||
function testInitialSetup() public { | ||
assertEq(avsCreator.delegationManager(), delegationManager); | ||
assertEq(avsCreator.avsDirectory(), avsDirectory); | ||
} | ||
|
||
// Test setting bytecode functions | ||
function testSetIndexRegistryBytecode() public { | ||
bytes memory bytecode = "dummyBytecode"; | ||
avsCreator.setIndexRegistryBytecode(bytecode); | ||
assertEq(avsCreator.indexRegistryBytecode(), bytecode); | ||
|
||
// Test to ensure it cannot be set again | ||
vm.expectRevert(AVSCreator.AlreadySet.selector); | ||
avsCreator.setIndexRegistryBytecode(bytecode); | ||
} | ||
|
||
function testSetStakeRegistryBytecode() public { | ||
bytes memory bytecode = "dummyBytecode"; | ||
avsCreator.setStakeRegistryBytecode(bytecode); | ||
assertEq(avsCreator.stakeRegistryBytecode(), bytecode); | ||
|
||
vm.expectRevert(AVSCreator.AlreadySet.selector); | ||
avsCreator.setStakeRegistryBytecode(bytecode); | ||
} | ||
|
||
function testSetApkRegistryBytecode() public { | ||
bytes memory bytecode = "dummyBytecode"; | ||
avsCreator.setApkRegistryBytecode(bytecode); | ||
assertEq(avsCreator.apkRegistryBytecode(), bytecode); | ||
|
||
vm.expectRevert(AVSCreator.AlreadySet.selector); | ||
avsCreator.setApkRegistryBytecode(bytecode); | ||
} | ||
|
||
function testSetRegistryCoordinatorBytecode() public { | ||
bytes memory bytecode = "dummyBytecode"; | ||
avsCreator.setRegistryCoordinatorBytecode(bytecode); | ||
assertEq(avsCreator.registryCoordinatorBytecode(), bytecode); | ||
|
||
vm.expectRevert(AVSCreator.AlreadySet.selector); | ||
avsCreator.setRegistryCoordinatorBytecode(bytecode); | ||
} | ||
|
||
function testSetServiceManagerBytecode() public { | ||
bytes memory bytecode = "dummyBytecode"; | ||
avsCreator.setServiceManagerBytecode(bytecode); | ||
assertEq(avsCreator.serviceManagerBytecode(), bytecode); | ||
|
||
vm.expectRevert(AVSCreator.AlreadySet.selector); | ||
avsCreator.setServiceManagerBytecode(bytecode); | ||
} | ||
|
||
// Test the creation of the AVS | ||
function testCreateAVS() public { | ||
// Ensure bytecode is set before creating AVS | ||
avsCreator.setIndexRegistryBytecode(type(IndexRegistry).creationCode); | ||
avsCreator.setStakeRegistryBytecode(type(StakeRegistry).creationCode); | ||
avsCreator.setApkRegistryBytecode(type(BLSApkRegistry).creationCode); | ||
avsCreator.setRegistryCoordinatorBytecode(type(RegistryCoordinator).creationCode); | ||
avsCreator.setServiceManagerBytecode(type(MachServiceManager).creationCode); | ||
|
||
// Call createAVS and check results | ||
( | ||
address indexRegistryProxy, | ||
address stakeRegistryProxy, | ||
address apkRegistryProxy, | ||
address registryCoordinatorProxy, | ||
address serviceManagerProxy, | ||
ProxyAdmin proxyAdmin | ||
) = avsCreator.createAVS(); | ||
|
||
assertTrue(indexRegistryProxy != address(0)); | ||
assertTrue(stakeRegistryProxy != address(0)); | ||
assertTrue(apkRegistryProxy != address(0)); | ||
assertTrue(registryCoordinatorProxy != address(0)); | ||
assertTrue(serviceManagerProxy != address(0)); | ||
assertTrue(address(proxyAdmin) != address(0)); | ||
} | ||
} |