Skip to content

Commit

Permalink
isolate contract and deployment script changes
Browse files Browse the repository at this point in the history
  • Loading branch information
afkbyte committed Oct 9, 2024
1 parent 191d4bc commit 1a94733
Show file tree
Hide file tree
Showing 11 changed files with 220 additions and 88 deletions.
12 changes: 11 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
AGGREGATOR_PUBLIC_KEY=0x68d30f47F19c07bCCEf4Ac7FAE2Dc12FCa3e0dC9
AGGREGATOR_RPC_LISTEN_SERVER=localhost:8080
AGGREGATOR_PRIVATE_KEY=59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d

DEPLOYER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

HOLESKY_PRIVATE_KEY=
HOLESKY_RPC_URL=


HELLOWORLD_OPERATORS_ECDSA_MNEMONIC="test test test test test test test test test test test junk"


4 changes: 3 additions & 1 deletion contracts/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
DEPLOYER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
AGGREGATOR_PRIVATE_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d

HOLESKY_PRIVATE_KEY=
HOLESKY_RPC_URL=
ETHERSCAN_API_KEY=
2 changes: 1 addition & 1 deletion contracts/script/DeployEigenLayerCore.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ contract DeployEigenlayerCore is Script {
CoreDeploymentLib.DeploymentConfigData internal configData;

function setUp() public virtual {
deployer = vm.rememberKey(vm.envUint("PRIVATE_KEY"));
deployer = vm.rememberKey(vm.envUint("DEPLOYER_PRIVATE_KEY"));
vm.label(deployer, "Deployer");
}

Expand Down
10 changes: 8 additions & 2 deletions contracts/script/HelloWorldDeployer.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ contract HelloWorldDeployer is Script {

address private deployer;
address proxyAdmin;
address aggregator;
CoreDeploymentLib.DeploymentData coreDeployment;
HelloWorldDeploymentLib.DeploymentData helloWorldDeployment;
Quorum internal quorum;

function setUp() public virtual {
deployer = vm.rememberKey(vm.envUint("PRIVATE_KEY"));
deployer = vm.rememberKey(vm.envUint("DEPLOYER_PRIVATE_KEY"));
vm.label(deployer, "Deployer");

coreDeployment = CoreDeploymentLib.readDeploymentJson("deployments/core/", block.chainid);
Expand All @@ -38,8 +39,12 @@ contract HelloWorldDeployer is Script {
vm.startBroadcast(deployer);
proxyAdmin = UpgradeableProxyLib.deployProxyAdmin();

aggregator = vm.addr(vm.envUint("AGGREGATOR_PRIVATE_KEY"));

console2.log("aggregator", aggregator);

helloWorldDeployment =
HelloWorldDeploymentLib.deployContracts(proxyAdmin, coreDeployment, quorum);
HelloWorldDeploymentLib.deployContracts(proxyAdmin, aggregator, coreDeployment, quorum);

vm.stopBroadcast();

Expand All @@ -56,6 +61,7 @@ contract HelloWorldDeployer is Script {
"HelloWorldServiceManager address cannot be zero"
);
require(proxyAdmin != address(0), "ProxyAdmin address cannot be zero");
require(aggregator != address(0), "Aggregator address cannot be zero");
require(
coreDeployment.delegationManager != address(0),
"DelegationManager address cannot be zero"
Expand Down
4 changes: 1 addition & 3 deletions contracts/script/utils/CoreDeploymentLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -378,9 +378,7 @@ library CoreDeploymentLib {
}

/// TODO: Need to be able to read json from eigenlayer-contracts repo for holesky/mainnet and output the json here
function writeDeploymentJson(
DeploymentData memory data
) internal {
function writeDeploymentJson(DeploymentData memory data) internal {
writeDeploymentJson("deployments/core/", block.chainid, data);
}

Expand Down
34 changes: 23 additions & 11 deletions contracts/script/utils/HelloWorldDeploymentLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ library HelloWorldDeploymentLib {

function deployContracts(
address proxyAdmin,
address aggregator,
CoreDeploymentLib.DeploymentData memory core,
Quorum memory quorum
) internal returns (DeploymentData memory) {
Expand All @@ -43,7 +44,7 @@ library HelloWorldDeploymentLib {
address(new ECDSAStakeRegistry(IDelegationManager(core.delegationManager)));
address helloWorldServiceManagerImpl = address(
new HelloWorldServiceManager(
core.avsDirectory, result.stakeRegistry, core.delegationManager
core.avsDirectory, result.stakeRegistry, core.delegationManager, aggregator
)
);
// Upgrade contracts
Expand All @@ -53,12 +54,17 @@ library HelloWorldDeploymentLib {
UpgradeableProxyLib.upgradeAndCall(result.stakeRegistry, stakeRegistryImpl, upgradeCall);
UpgradeableProxyLib.upgrade(result.helloWorldServiceManager, helloWorldServiceManagerImpl);

// Initialize HelloWorldServiceManager with aggregator
bytes memory helloWorldInitCall =
abi.encodeCall(HelloWorldServiceManager.initialize, (aggregator));
UpgradeableProxyLib.upgradeAndCall(
result.helloWorldServiceManager, helloWorldServiceManagerImpl, helloWorldInitCall
);

return result;
}

function readDeploymentJson(
uint256 chainId
) internal returns (DeploymentData memory) {
function readDeploymentJson(uint256 chainId) internal returns (DeploymentData memory) {
return readDeploymentJson("deployments/", chainId);
}

Expand All @@ -81,9 +87,7 @@ library HelloWorldDeploymentLib {
}

/// write to default output path
function writeDeploymentJson(
DeploymentData memory data
) internal {
function writeDeploymentJson(DeploymentData memory data) internal {
writeDeploymentJson("deployments/hello-world/", block.chainid, data);
}

Expand All @@ -95,7 +99,11 @@ library HelloWorldDeploymentLib {
address proxyAdmin =
address(UpgradeableProxyLib.getProxyAdmin(data.helloWorldServiceManager));

string memory deploymentData = _generateDeploymentJson(data, proxyAdmin);
address aggregator = HelloWorldServiceManager(data.helloWorldServiceManager).aggregator();

console2.log("aggregator2", aggregator);

string memory deploymentData = _generateDeploymentJson(data, proxyAdmin, aggregator);

string memory fileName = string.concat(outputPath, vm.toString(chainId), ".json");
if (!vm.exists(outputPath)) {
Expand All @@ -108,26 +116,30 @@ library HelloWorldDeploymentLib {

function _generateDeploymentJson(
DeploymentData memory data,
address proxyAdmin
address proxyAdmin,
address aggregator
) private view returns (string memory) {
return string.concat(
'{"lastUpdate":{"timestamp":"',
vm.toString(block.timestamp),
'","block_number":"',
vm.toString(block.number),
'"},"addresses":',
_generateContractsJson(data, proxyAdmin),
_generateContractsJson(data, proxyAdmin, aggregator),
"}"
);
}

function _generateContractsJson(
DeploymentData memory data,
address proxyAdmin
address proxyAdmin,
address aggregator
) private view returns (string memory) {
return string.concat(
'{"proxyAdmin":"',
proxyAdmin.toHexString(),
'","aggregator":"',
aggregator.toHexString(),
'","helloWorldServiceManager":"',
data.helloWorldServiceManager.toHexString(),
'","helloWorldServiceManagerImpl":"',
Expand Down
12 changes: 3 additions & 9 deletions contracts/script/utils/UpgradeableProxyLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ library UpgradeableProxyLib {
return address(new ProxyAdmin());
}

function setUpEmptyProxy(
address admin
) internal returns (address) {
function setUpEmptyProxy(address admin) internal returns (address) {
address emptyContract = address(new EmptyContract());
return address(new TransparentUpgradeableProxy(emptyContract, admin, ""));
}
Expand All @@ -36,16 +34,12 @@ library UpgradeableProxyLib {
admin.upgradeAndCall(TransparentUpgradeableProxy(payable(proxy)), impl, initData);
}

function getImplementation(
address proxy
) internal view returns (address) {
function getImplementation(address proxy) internal view returns (address) {
bytes32 value = vm.load(proxy, IMPLEMENTATION_SLOT);
return address(uint160(uint256(value)));
}

function getProxyAdmin(
address proxy
) internal view returns (ProxyAdmin) {
function getProxyAdmin(address proxy) internal view returns (ProxyAdmin) {
bytes32 value = vm.load(proxy, ADMIN_SLOT);
return ProxyAdmin(address(uint160(uint256(value))));
}
Expand Down
78 changes: 56 additions & 22 deletions contracts/src/HelloWorldServiceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {ECDSAStakeRegistry} from "@eigenlayer-middleware/src/unaudited/ECDSAStak
import {IServiceManager} from "@eigenlayer-middleware/src/interfaces/IServiceManager.sol";
import {ECDSAUpgradeable} from
"@openzeppelin-upgrades/contracts/utils/cryptography/ECDSAUpgradeable.sol";
import {IERC1271Upgradeable} from "@openzeppelin-upgrades/contracts/interfaces/IERC1271Upgradeable.sol";
import {IERC1271Upgradeable} from
"@openzeppelin-upgrades/contracts/interfaces/IERC1271Upgradeable.sol";
import {IHelloWorldServiceManager} from "./IHelloWorldServiceManager.sol";
import "@openzeppelin/contracts/utils/Strings.sol";

Expand All @@ -20,27 +21,29 @@ contract HelloWorldServiceManager is ECDSAServiceManagerBase, IHelloWorldService

uint32 public latestTaskNum;

address public aggregator;

// mapping of task indices to all tasks hashes
// when a task is created, task hash is stored here,
// and responses need to pass the actual task,
// which is hashed onchain and checked against this mapping
mapping(uint32 => bytes32) public allTaskHashes;

// mapping of task indices to hash of abi.encode(taskResponse, taskResponseMetadata)
mapping(address => mapping(uint32 => bytes)) public allTaskResponses;
mapping(uint32 => bytes) public allTaskResponses;

modifier onlyOperator() {
require(
ECDSAStakeRegistry(stakeRegistry).operatorRegistered(msg.sender),
"Operator must be the caller"
);
modifier onlyAggregator() {
if (msg.sender != aggregator) {
revert("Aggregator must be the caller");
}
_;
}

constructor(
address _avsDirectory,
address _stakeRegistry,
address _delegationManager
address _delegationManager,
address _aggregator
)
ECDSAServiceManagerBase(
_avsDirectory,
Expand All @@ -50,11 +53,13 @@ contract HelloWorldServiceManager is ECDSAServiceManagerBase, IHelloWorldService
)
{}

function initialize(address _aggregator) public initializer {
_updateAggregator(_aggregator);
}

/* FUNCTIONS */
// NOTE: this function creates new task, assigns it a taskId
function createNewTask(
string memory name
) external returns (Task memory) {
function createNewTask(string memory name) external returns (Task memory) {
// create a new task struct
Task memory newTask;
newTask.name = name;
Expand All @@ -71,30 +76,59 @@ contract HelloWorldServiceManager is ECDSAServiceManagerBase, IHelloWorldService
function respondToTask(
Task calldata task,
uint32 referenceTaskIndex,
bytes memory signature
) external {
bytes memory aggregateSignatureData
) external onlyAggregator {
// check that the task is valid, hasn't been responsed yet, and is being responded in time
require(
keccak256(abi.encode(task)) == allTaskHashes[referenceTaskIndex],
"supplied task does not match the one recorded in the contract"
);
require(
allTaskResponses[msg.sender][referenceTaskIndex].length == 0,
"Operator has already responded to the task"
);

// The message that was signed
bytes32 messageHash = keccak256(abi.encodePacked("Hello, ", task.name));
bytes32 ethSignedMessageHash = messageHash.toEthSignedMessageHash();

(address[] memory operators, bytes[] memory signatures, uint32 referenceBlock) =
abi.decode(aggregateSignatureData, (address[], bytes[], uint32));

// check if all signers are registered operators
// @note is this necessary? _checkSignatures requires that the total signer weight meets our threshold
// only registered operators can contribute to the weight.
for (uint256 i = 0; i < operators.length; i++) {
require(_isOperator(operators[i]), "Invalid signer: not registered as operator");
}

// check if signatures are valid
bytes4 magicValue = IERC1271Upgradeable.isValidSignature.selector;
if (!(magicValue == ECDSAStakeRegistry(stakeRegistry).isValidSignature(ethSignedMessageHash,signature))){
revert();
bytes32 ethSignedMessageHash = messageHash.toEthSignedMessageHash();
if (
!(
magicValue
== ECDSAStakeRegistry(stakeRegistry).isValidSignature(
ethSignedMessageHash, aggregateSignatureData
)
)
) {
revert("Invalid signature");
}

// updating the storage with task responses
allTaskResponses[msg.sender][referenceTaskIndex] = signature;
// updating the storage with task response
allTaskResponses[referenceTaskIndex] = aggregateSignatureData;

// emitting event
emit TaskResponded(referenceTaskIndex, task, msg.sender);
}

function updateAggregator(address _newAggregator) external onlyOwner {
_updateAggregator(_newAggregator);
}

function _isOperator(address _operator) internal view returns (bool) {
return ECDSAStakeRegistry(stakeRegistry).operatorRegistered(_operator);
}

function _updateAggregator(address _newAggregator) internal {
address oldAggregator = aggregator;
aggregator = _newAggregator;
emit AggregatorUpdated(oldAggregator, _newAggregator);
}
}
17 changes: 7 additions & 10 deletions contracts/src/IHelloWorldServiceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,22 @@ interface IHelloWorldServiceManager {

event TaskResponded(uint32 indexed taskIndex, Task task, address operator);

event AggregatorUpdated(address oldAggregator, address newAggregator);

struct Task {
string name;
uint32 taskCreatedBlock;
}

function latestTaskNum() external view returns (uint32);

function allTaskHashes(
uint32 taskIndex
) external view returns (bytes32);
function aggregator() external view returns (address);

function allTaskHashes(uint32 taskIndex) external view returns (bytes32);

function allTaskResponses(
address operator,
uint32 taskIndex
) external view returns (bytes memory);
function allTaskResponses(uint32 taskIndex) external view returns (bytes memory);

function createNewTask(
string memory name
) external returns (Task memory);
function createNewTask(string memory name) external returns (Task memory);

function respondToTask(
Task calldata task,
Expand Down
2 changes: 1 addition & 1 deletion contracts/test/ERC20Mock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract ERC20Mock is ERC20 {
constructor() ERC20("", "") {}

function mint(address account, uint256 amount) public {
_mint(account, amount);
}
Expand Down
Loading

0 comments on commit 1a94733

Please sign in to comment.