Skip to content

Commit

Permalink
feat: AVS Creator
Browse files Browse the repository at this point in the history
  • Loading branch information
neutiyoo committed Jul 17, 2024
1 parent 8bab509 commit 5810dfb
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 0 deletions.
50 changes: 50 additions & 0 deletions contracts/script/AVSCreatorDeployer.s.sol
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();
}
}
132 changes: 132 additions & 0 deletions contracts/src/core/AVSCreator.sol
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;
}
}
100 changes: 100 additions & 0 deletions contracts/test/AVSCreator.t.sol
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));
}
}

0 comments on commit 5810dfb

Please sign in to comment.