diff --git a/.github/workflows/validate_pr.yml b/.github/workflows/validate_pr.yml index 9491171..9b1d478 100644 --- a/.github/workflows/validate_pr.yml +++ b/.github/workflows/validate_pr.yml @@ -94,6 +94,9 @@ jobs: steps: - name: checkout code uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 - name: Install Foundry run: | diff --git a/README.md b/README.md index aa12535..19e66af 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ Incredible Squaring AVS cargo test -p test-utils test_incredible_squaring_full ``` -These full test starts a local Anvil testnet, deploys all the required contracts to it, and then starts an operator. +These full tests start a local Anvil testnet, deploy all the required contracts to it, and then start an operator. ### Running the Testnets as binaries diff --git a/avs/incredible-squaring-avs/.github/workflows/test.yml b/avs/incredible-squaring-avs/.github/workflows/test.yml deleted file mode 100644 index 09880b1..0000000 --- a/avs/incredible-squaring-avs/.github/workflows/test.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: test - -on: workflow_dispatch - -env: - FOUNDRY_PROFILE: ci - -jobs: - check: - strategy: - fail-fast: true - - name: Foundry project - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - - name: Run Forge build - run: | - forge --version - forge build --sizes - id: build - - - name: Run Forge tests - run: | - forge test -vvv - id: test diff --git a/avs/incredible-squaring-avs/build.rs b/avs/incredible-squaring-avs/build.rs index 122809f..5c21750 100644 --- a/avs/incredible-squaring-avs/build.rs +++ b/avs/incredible-squaring-avs/build.rs @@ -4,7 +4,12 @@ use std::process::Command; fn main() { // List of directories containing Solidity contracts - let contract_dirs = vec!["./contracts"]; + let contract_dirs: Vec<&str> = vec![ + "./../contracts/lib/eigenlayer-middleware/lib/eigenlayer-contracts", + "./../contracts/lib/eigenlayer-middleware", + "./../contracts", + "./contracts", + ]; // Get the project root directory let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); diff --git a/avs/incredible-squaring-avs/src/operator.rs b/avs/incredible-squaring-avs/src/operator.rs index 0e84bd0..f6e0669 100644 --- a/avs/incredible-squaring-avs/src/operator.rs +++ b/avs/incredible-squaring-avs/src/operator.rs @@ -10,6 +10,7 @@ use crate::rpc_client::AggregatorRpcClient; use alloy_contract::private::Ethereum; use alloy_primitives::{Address, Bytes, ChainId, FixedBytes, Signature, B256, U256}; use alloy_provider::{Provider, RootProvider}; +use alloy_pubsub::Subscription; use alloy_rpc_types::Log; use alloy_signer_local::PrivateKeySigner; use alloy_sol_types::SolValue; @@ -85,8 +86,8 @@ pub struct Operator { operator_id: FixedBytes<32>, operator_addr: Address, aggregator_server_ip_port_addr: String, - aggregator_server: Aggregator, - aggregator_rpc_client: AggregatorRpcClient, + pub aggregator_server: Aggregator, + pub aggregator_rpc_client: AggregatorRpcClient, } #[derive(Clone)] @@ -156,6 +157,7 @@ pub struct NodeConfig { pub server_ip_port_address: String, pub operator_address: String, pub enable_metrics: bool, + pub metadata_url: String, } impl Config for NodeConfig { @@ -283,7 +285,7 @@ impl Operator { earnings_receiver_address: operator_address, delegation_approver_address: Address::from([0u8; 20]), staker_opt_out_window_blocks: 50400u32, // About 7 days in blocks on Ethereum - metadata_url: "https://github.com/webb-tools/eigensdk-rs/blob/donovan/eigen/test-utils/metadata.json".to_string(), + metadata_url: config.metadata_url.clone(), }; let eigenlayer_register_result = eigenlayer_contract_manager .register_as_operator(register_operator) @@ -360,11 +362,7 @@ impl Operator { return Err(OperatorError::NodeApiError(e.to_string())); } } - let mut sub = self - .incredible_squaring_contract_manager - .subscribe_to_new_tasks() - .await - .unwrap(); + let mut sub = self.subscribe_to_new_tasks().await?; let server = self.aggregator_server.clone(); let aggregator_server = async move { @@ -402,7 +400,7 @@ impl Operator { self.config.clone() } - fn process_new_task_created_log( + pub fn process_new_task_created_log( &self, new_task_created_log: &Log, ) -> IncredibleSquaringTaskManager::TaskResponse { @@ -425,7 +423,7 @@ impl Operator { } } - fn sign_task_response( + pub fn sign_task_response( &self, task_response: &IncredibleSquaringTaskManager::TaskResponse, ) -> Result { @@ -439,4 +437,18 @@ impl Operator { log::debug!("Signed task response: {:?}", signed_task_response); Ok(signed_task_response) } + + pub async fn subscribe_to_new_tasks(&self) -> Result, AvsError> { + self.incredible_squaring_contract_manager + .subscribe_to_new_tasks() + .await + } + + pub async fn start_aggregator_server(&self) -> Result<(), AvsError> { + self.aggregator_server + .clone() + .start_server() + .await + .map_err(|e| AvsError::OperatorError(e.to_string())) + } } diff --git a/avs/tangle-avs/build.rs b/avs/tangle-avs/build.rs index 122809f..5c21750 100644 --- a/avs/tangle-avs/build.rs +++ b/avs/tangle-avs/build.rs @@ -4,7 +4,12 @@ use std::process::Command; fn main() { // List of directories containing Solidity contracts - let contract_dirs = vec!["./contracts"]; + let contract_dirs: Vec<&str> = vec![ + "./../contracts/lib/eigenlayer-middleware/lib/eigenlayer-contracts", + "./../contracts/lib/eigenlayer-middleware", + "./../contracts", + "./contracts", + ]; // Get the project root directory let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); diff --git a/avs/tangle-avs/src/operator.rs b/avs/tangle-avs/src/operator.rs index b3c6d2f..a25c122 100644 --- a/avs/tangle-avs/src/operator.rs +++ b/avs/tangle-avs/src/operator.rs @@ -90,6 +90,7 @@ pub struct NodeConfig { pub operator_address: String, pub enable_metrics: bool, pub enable_node_api: bool, + pub metadata_url: String, } #[derive(Clone)] @@ -241,7 +242,7 @@ impl Operator { earnings_receiver_address: operator_addr, delegation_approver_address: Address::from([0u8; 20]), staker_opt_out_window_blocks: 50400u32, // About 7 days in blocks on Ethereum - metadata_url: "https://github.com/webb-tools/eigensdk-rs/blob/donovan/eigen/test-utils/metadata.json".to_string(), + metadata_url: config.metadata_url.clone(), }; let eigenlayer_register_result = eigenlayer_contract_manager .register_as_operator(register_operator) diff --git a/contracts/IncredibleSquaringDeployer.s.sol b/contracts/IncredibleSquaringDeployer.s.sol deleted file mode 100644 index 55e2234..0000000 --- a/contracts/IncredibleSquaringDeployer.s.sol +++ /dev/null @@ -1,454 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.12; - -import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; - -import "lib/eigenlayer-contracts/src/contracts/permissions/PauserRegistry.sol"; -import {IDelegationManager} from "lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; -import {IAVSDirectory} from "lib/eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol"; -import {IStrategyManager, IStrategy} from "lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; -import {ISlasher} from "lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol"; -import {StrategyBaseTVLLimits} from "lib/eigenlayer-contracts/src/contracts/strategies/StrategyBaseTVLLimits.sol"; -import "lib/eigenlayer-contracts/src/test/mocks/EmptyContract.sol"; - -import "eigenlayer-middleware/src/RegistryCoordinator.sol" as regcoord; -import {IBLSApkRegistry, IIndexRegistry, IStakeRegistry} from "eigenlayer-middleware/src/RegistryCoordinator.sol"; -import {BLSApkRegistry} from "eigenlayer-middleware/src/BLSApkRegistry.sol"; -import {IndexRegistry} from "eigenlayer-middleware/src/IndexRegistry.sol"; -import {StakeRegistry} from "eigenlayer-middleware/src/StakeRegistry.sol"; -import "eigenlayer-middleware/src/OperatorStateRetriever.sol"; - -import {IncredibleSquaringServiceManager, IServiceManager} from "incredible-squaring-avs/contracts/src/IncredibleSquaringServiceManager.sol"; -import {IncredibleSquaringTaskManager} from "incredible-squaring-avs/contracts/src/IncredibleSquaringTaskManager.sol"; -import {IIncredibleSquaringTaskManager} from "incredible-squaring-avs/contracts/src/IIncredibleSquaringTaskManager.sol"; -import "incredible-squaring-avs/contracts/src/ERC20Mock.sol"; - -import {Utils} from "./utils/Utils.sol"; - -import "forge-std/Test.sol"; -import "forge-std/Script.sol"; -import "forge-std/StdJson.sol"; -import "forge-std/console.sol"; - -// # To deploy and verify our contract -// forge script script/CredibleSquaringDeployer.s.sol:CredibleSquaringDeployer --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast -vvvv -contract IncredibleSquaringDeployer is Script, Utils { - // DEPLOYMENT CONSTANTS - uint256 public constant QUORUM_THRESHOLD_PERCENTAGE = 100; - uint32 public constant TASK_RESPONSE_WINDOW_BLOCK = 30; - uint32 public constant TASK_DURATION_BLOCKS = 0; - // TODO: right now hardcoding these (this address is anvil's default address 9) - address public constant AGGREGATOR_ADDR = - 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720; - address public constant TASK_GENERATOR_ADDR = - 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720; - - // ERC20 and Strategy: we need to deploy this erc20, create a strategy for it, and whitelist this strategy in the strategymanager - - ERC20Mock public erc20Mock; - StrategyBaseTVLLimits public erc20MockStrategy; - - // Credible Squaring contracts - ProxyAdmin public incredibleSquaringProxyAdmin; - PauserRegistry public incredibleSquaringPauserReg; - - regcoord.RegistryCoordinator public registryCoordinator; - regcoord.IRegistryCoordinator public registryCoordinatorImplementation; - - IBLSApkRegistry public blsApkRegistry; - IBLSApkRegistry public blsApkRegistryImplementation; - - IIndexRegistry public indexRegistry; - IIndexRegistry public indexRegistryImplementation; - - IStakeRegistry public stakeRegistry; - IStakeRegistry public stakeRegistryImplementation; - - OperatorStateRetriever public operatorStateRetriever; - - IncredibleSquaringServiceManager public incredibleSquaringServiceManager; - IServiceManager public incredibleSquaringServiceManagerImplementation; - - IncredibleSquaringTaskManager public incredibleSquaringTaskManager; - IIncredibleSquaringTaskManager - public incredibleSquaringTaskManagerImplementation; - - function run() external { - // Eigenlayer contracts - string memory eigenlayerDeployedContracts = readOutput( - "eigenlayer_deployment_output" - ); - IStrategyManager strategyManager = IStrategyManager( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.strategyManager" - ) - ); - IDelegationManager delegationManager = IDelegationManager( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.delegation" - ) - ); - IAVSDirectory avsDirectory = IAVSDirectory( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.avsDirectory" - ) - ); - ProxyAdmin eigenLayerProxyAdmin = ProxyAdmin( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.eigenLayerProxyAdmin" - ) - ); - PauserRegistry eigenLayerPauserReg = PauserRegistry( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.eigenLayerPauserReg" - ) - ); - StrategyBaseTVLLimits baseStrategyImplementation = StrategyBaseTVLLimits( - stdJson.readAddress( - eigenlayerDeployedContracts, - ".addresses.baseStrategyImplementation" - ) - ); - - address credibleSquaringCommunityMultisig = msg.sender; - address credibleSquaringPauser = msg.sender; - - vm.startBroadcast(); - _deployErc20AndStrategyAndWhitelistStrategy( - eigenLayerProxyAdmin, - eigenLayerPauserReg, - baseStrategyImplementation, - strategyManager - ); - _deployCredibleSquaringContracts( - delegationManager, - avsDirectory, - erc20MockStrategy, - credibleSquaringCommunityMultisig, - credibleSquaringPauser - ); - vm.stopBroadcast(); - } - - function _deployErc20AndStrategyAndWhitelistStrategy( - ProxyAdmin eigenLayerProxyAdmin, - PauserRegistry eigenLayerPauserReg, - StrategyBaseTVLLimits baseStrategyImplementation, - IStrategyManager strategyManager - ) internal { - erc20Mock = new ERC20Mock(); - // TODO(samlaf): any reason why we are using the strategybase with tvl limits instead of just using strategybase? - // the maxPerDeposit and maxDeposits below are just arbitrary values. - erc20MockStrategy = StrategyBaseTVLLimits( - address( - new TransparentUpgradeableProxy( - address(baseStrategyImplementation), - address(eigenLayerProxyAdmin), - abi.encodeWithSelector( - StrategyBaseTVLLimits.initialize.selector, - 1 ether, // maxPerDeposit - 100 ether, // maxDeposits - IERC20(erc20Mock), - eigenLayerPauserReg - ) - ) - ) - ); - IStrategy[] memory strats = new IStrategy[](1); - strats[0] = erc20MockStrategy; - bool[] memory thirdPartyTransfersForbiddenValues = new bool[](1); - thirdPartyTransfersForbiddenValues[0] = false; - strategyManager.addStrategiesToDepositWhitelist( - strats, - thirdPartyTransfersForbiddenValues - ); - } - - function _deployCredibleSquaringContracts( - IDelegationManager delegationManager, - IAVSDirectory avsDirectory, - IStrategy strat, - address incredibleSquaringCommunityMultisig, - address credibleSquaringPauser - ) internal { - // Adding this as a temporary fix to make the rest of the script work with a single strategy - // since it was originally written to work with an array of strategies - IStrategy[1] memory deployedStrategyArray = [strat]; - uint numStrategies = deployedStrategyArray.length; - - // deploy proxy admin for ability to upgrade proxy contracts - incredibleSquaringProxyAdmin = new ProxyAdmin(); - - // deploy pauser registry - { - address[] memory pausers = new address[](2); - pausers[0] = credibleSquaringPauser; - pausers[1] = incredibleSquaringCommunityMultisig; - incredibleSquaringPauserReg = new PauserRegistry( - pausers, - incredibleSquaringCommunityMultisig - ); - } - - EmptyContract emptyContract = new EmptyContract(); - - // hard-coded inputs - - /** - * First, deploy upgradeable proxy contracts that **will point** to the implementations. Since the implementation contracts are - * not yet deployed, we give these proxies an empty contract as the initial implementation, to act as if they have no code. - */ - incredibleSquaringServiceManager = IncredibleSquaringServiceManager( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) - ); - incredibleSquaringTaskManager = IncredibleSquaringTaskManager( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) - ); - registryCoordinator = regcoord.RegistryCoordinator( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) - ); - blsApkRegistry = IBLSApkRegistry( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) - ); - indexRegistry = IIndexRegistry( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) - ); - stakeRegistry = IStakeRegistry( - address( - new TransparentUpgradeableProxy( - address(emptyContract), - address(incredibleSquaringProxyAdmin), - "" - ) - ) - ); - - operatorStateRetriever = new OperatorStateRetriever(); - - // Second, deploy the *implementation* contracts, using the *proxy contracts* as inputs - { - stakeRegistryImplementation = new StakeRegistry( - registryCoordinator, - delegationManager - ); - - incredibleSquaringProxyAdmin.upgrade( - TransparentUpgradeableProxy(payable(address(stakeRegistry))), - address(stakeRegistryImplementation) - ); - - blsApkRegistryImplementation = new BLSApkRegistry( - registryCoordinator - ); - - incredibleSquaringProxyAdmin.upgrade( - TransparentUpgradeableProxy(payable(address(blsApkRegistry))), - address(blsApkRegistryImplementation) - ); - - indexRegistryImplementation = new IndexRegistry( - registryCoordinator - ); - - incredibleSquaringProxyAdmin.upgrade( - TransparentUpgradeableProxy(payable(address(indexRegistry))), - address(indexRegistryImplementation) - ); - } - - registryCoordinatorImplementation = new regcoord.RegistryCoordinator( - incredibleSquaringServiceManager, - regcoord.IStakeRegistry(address(stakeRegistry)), - regcoord.IBLSApkRegistry(address(blsApkRegistry)), - regcoord.IIndexRegistry(address(indexRegistry)) - ); - - { - uint numQuorums = 1; - // for each quorum to setup, we need to define - // QuorumOperatorSetParam, minimumStakeForQuorum, and strategyParams - regcoord.IRegistryCoordinator.OperatorSetParam[] - memory quorumsOperatorSetParams = new regcoord.IRegistryCoordinator.OperatorSetParam[]( - numQuorums - ); - for (uint i = 0; i < numQuorums; i++) { - // hard code these for now - quorumsOperatorSetParams[i] = regcoord - .IRegistryCoordinator - .OperatorSetParam({ - maxOperatorCount: 10000, - kickBIPsOfOperatorStake: 15000, - kickBIPsOfTotalStake: 100 - }); - } - // set to 0 for every quorum - uint96[] memory quorumsMinimumStake = new uint96[](numQuorums); - IStakeRegistry.StrategyParams[][] - memory quorumsStrategyParams = new IStakeRegistry.StrategyParams[][]( - numQuorums - ); - for (uint i = 0; i < numQuorums; i++) { - quorumsStrategyParams[i] = new IStakeRegistry.StrategyParams[]( - numStrategies - ); - for (uint j = 0; j < numStrategies; j++) { - quorumsStrategyParams[i][j] = IStakeRegistry - .StrategyParams({ - strategy: deployedStrategyArray[j], - // setting this to 1 ether since the divisor is also 1 ether - // therefore this allows an operator to register with even just 1 token - // see https://github.com/Layr-Labs/eigenlayer-middleware/blob/m2-mainnet/src/StakeRegistry.sol#L484 - // weight += uint96(sharesAmount * strategyAndMultiplier.multiplier / WEIGHTING_DIVISOR); - multiplier: 1 ether - }); - } - } - incredibleSquaringProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy( - payable(address(registryCoordinator)) - ), - address(registryCoordinatorImplementation), - abi.encodeWithSelector( - regcoord.RegistryCoordinator.initialize.selector, - // we set churnApprover and ejector to communityMultisig because we don't need them - incredibleSquaringCommunityMultisig, - incredibleSquaringCommunityMultisig, - incredibleSquaringCommunityMultisig, - incredibleSquaringPauserReg, - 0, // 0 initialPausedStatus means everything unpaused - quorumsOperatorSetParams, - quorumsMinimumStake, - quorumsStrategyParams - ) - ); - } - - incredibleSquaringServiceManagerImplementation = new IncredibleSquaringServiceManager( - avsDirectory, - registryCoordinator, - stakeRegistry, - incredibleSquaringTaskManager - ); - // Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them. - incredibleSquaringProxyAdmin.upgrade( - TransparentUpgradeableProxy( - payable(address(incredibleSquaringServiceManager)) - ), - address(incredibleSquaringServiceManagerImplementation) - ); - - incredibleSquaringTaskManagerImplementation = new IncredibleSquaringTaskManager( - registryCoordinator, - TASK_RESPONSE_WINDOW_BLOCK - ); - - // Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them. - incredibleSquaringProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy( - payable(address(incredibleSquaringTaskManager)) - ), - address(incredibleSquaringTaskManagerImplementation), - abi.encodeWithSelector( - incredibleSquaringTaskManager.initialize.selector, - incredibleSquaringPauserReg, - incredibleSquaringCommunityMultisig, - AGGREGATOR_ADDR, - TASK_GENERATOR_ADDR - ) - ); - - // WRITE JSON DATA - string memory parent_object = "parent object"; - - string memory deployed_addresses = "addresses"; - vm.serializeAddress( - deployed_addresses, - "erc20Mock", - address(erc20Mock) - ); - vm.serializeAddress( - deployed_addresses, - "erc20MockStrategy", - address(erc20MockStrategy) - ); - vm.serializeAddress( - deployed_addresses, - "credibleSquaringServiceManager", - address(incredibleSquaringServiceManager) - ); - vm.serializeAddress( - deployed_addresses, - "credibleSquaringServiceManagerImplementation", - address(incredibleSquaringServiceManagerImplementation) - ); - vm.serializeAddress( - deployed_addresses, - "credibleSquaringTaskManager", - address(incredibleSquaringTaskManager) - ); - vm.serializeAddress( - deployed_addresses, - "credibleSquaringTaskManagerImplementation", - address(incredibleSquaringTaskManagerImplementation) - ); - vm.serializeAddress( - deployed_addresses, - "registryCoordinator", - address(registryCoordinator) - ); - vm.serializeAddress( - deployed_addresses, - "registryCoordinatorImplementation", - address(registryCoordinatorImplementation) - ); - string memory deployed_addresses_output = vm.serializeAddress( - deployed_addresses, - "operatorStateRetriever", - address(operatorStateRetriever) - ); - - // serialize all the data - string memory finalJson = vm.serializeString( - parent_object, - deployed_addresses, - deployed_addresses_output - ); - - writeOutput(finalJson, "credible_squaring_avs_deployment_output"); - } -} \ No newline at end of file diff --git a/contracts/README.md b/contracts/README.md deleted file mode 100644 index 53f5faf..0000000 --- a/contracts/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Eigen Layer contract Ethers bindings - --- Run `generate_abi_json.sh` to generate updated json files. \ No newline at end of file diff --git a/contracts/build.rs b/contracts/build.rs index f2228b1..40c4ee1 100644 --- a/contracts/build.rs +++ b/contracts/build.rs @@ -4,10 +4,12 @@ use std::process::Command; fn main() { // List of directories containing Solidity contracts - let contract_dirs = vec![ + let contract_dirs: Vec<&str> = vec![ "./lib/eigenlayer-middleware/lib/eigenlayer-contracts", "./lib/eigenlayer-middleware", "./", + "./../avs/tangle-avs/contracts", + "./../avs/incredible-squaring-avs/contracts", ]; // Get the project root directory diff --git a/contracts/utils/generate_abi_json.sh b/contracts/utils/generate_abi_json.sh deleted file mode 100755 index 1a7df74..0000000 --- a/contracts/utils/generate_abi_json.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -forge build - -cargo b -r diff --git a/test-utils/README.md b/test-utils/README.md index dbef63e..534f2c3 100644 --- a/test-utils/README.md +++ b/test-utils/README.md @@ -58,18 +58,12 @@ To run the tests for the included AVSs (from the test-utils directory): #### Tangle ```bash -# To just run the deployment test, running the Testnet -cargo test test_tangle_deployment - # To run the testnet and test connecting an Operator to it -cargo test test_full_tangle +cargo test -p test-utils test_tangle_full ``` #### Incredible Squaring ```bash -# To just run the deployment test, running the Testnet -cargo test test_incredible_squaring_deployment - # To run the testnet and test connecting an Operator to it -cargo test test_full_incredible_squaring +cargo test -p test-utils test_incredible_squaring_full ``` diff --git a/test-utils/src/bin/incredible_squaring.rs b/test-utils/src/bin/incredible_squaring.rs index 7c51667..6662b76 100644 --- a/test-utils/src/bin/incredible_squaring.rs +++ b/test-utils/src/bin/incredible_squaring.rs @@ -36,6 +36,9 @@ async fn operator_setup( enable_metrics: false, enable_node_api: false, server_ip_port_address: "127.0.0.1:8673".to_string(), + metadata_url: + "https://github.com/webb-tools/eigensdk-rs/blob/main/test-utils/metadata.json" + .to_string(), }; let operator_info_service = OperatorInfoService {}; @@ -88,6 +91,8 @@ async fn operator_setup( #[cfg(test)] mod tests { use super::*; + use alloy_rpc_types_eth::Log; + use incredible_squaring_avs::avs::IncredibleSquaringTaskManager; use std::env; fn env_init() { @@ -118,6 +123,33 @@ mod tests { // Check that the operator has registered successfully assert!(operator.is_registered().await.unwrap()); - log::info!("Operator Successfully Registered. The Tangle Validator would now start."); + let mut sub = operator.subscribe_to_new_tasks().await.unwrap(); + log::info!("Subscribed to new tasks: {:?}", sub); + + let server = operator.aggregator_server.clone(); + let aggregator_server = async move { + server.start_server().await.unwrap(); + }; + tokio::spawn(aggregator_server); + + let new_task_created_log = sub.recv().await.unwrap(); + log::info!("Received new task: {:?}", new_task_created_log); + + let log: Log = + new_task_created_log.log_decode().unwrap(); + let task_response = operator.process_new_task_created_log(&log); + log::info!("Generated Task Response: {:?}", task_response); + if let Ok(signed_task_response) = operator.sign_task_response(&task_response) { + log::info!( + "Sending signed task response to aggregator: {:?}", + signed_task_response + ); + let agg_rpc_client = operator.aggregator_rpc_client.clone(); + tokio::spawn(async move { + agg_rpc_client + .send_signed_task_response_to_aggregator(signed_task_response) + .await; + }); + } } } diff --git a/test-utils/src/bin/tangle.rs b/test-utils/src/bin/tangle.rs index 8b5c4f3..8e26228 100644 --- a/test-utils/src/bin/tangle.rs +++ b/test-utils/src/bin/tangle.rs @@ -33,6 +33,9 @@ async fn operator_setup(contract_addresses: ContractAddresses) -> Operator { + let path = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if path.is_empty() { + panic!("Forge executable not found. Make sure Foundry is installed."); + } + path + } + Err(_) => panic!("Failed to locate `forge` executable. Make sure Foundry is installed."), + }; + + for dir in contract_dirs { + let full_path = root.join(dir).canonicalize().unwrap_or_else(|_| { + println!( + "Directory not found or inaccessible: {}", + root.join(dir).display() + ); + root.join(dir) + }); + + if full_path.exists() { + println!("cargo:rerun-if-changed={}", full_path.display()); + + let status = Command::new(&forge_executable) + .current_dir(&full_path) + .arg("build") + .status() + .expect("Failed to execute Forge build"); + + if !status.success() { + panic!("Forge build failed for directory: {}", full_path.display()); + } + } else { + println!( + "Directory not found or does not exist: {}", + full_path.display() + ); + } + } +}