Skip to content

Commit c323886

Browse files
authored
improved service manager script flow (#15)
* clean docker, script get service manager * remove deployment docker requirement * `make start-all` * `loadEigenContractsFromFS` instead of jq read into env * simplify, more make helpers
1 parent 9306574 commit c323886

File tree

4 files changed

+86
-75
lines changed

4 files changed

+86
-75
lines changed

Makefile

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ default: build
77
CARGO=cargo
88

99
## bindings: generating bindings
10-
bindings:
10+
bindings: _build_forge
1111
# Generate new bindings
1212
@forge bind --bindings-path ./crates/bindings --crate-name bindings --overwrite \
1313
--alloy --alloy-version v0.9.2
14+
@$(CARGO) fmt --manifest-path ./crates/bindings/Cargo.toml
1415

1516
## build: building the project
16-
build: bindings wasi-build
17+
build: _build_forge bindings wasi-build
1718
@$(CARGO) build --target-dir ./target --manifest-path ./app/Cargo.toml
1819

1920
## wasi-build: building the WAVS wasi component(s)
@@ -25,19 +26,19 @@ wasi-build:
2526
@mkdir -p ./compiled
2627
@cp ./target/wasm32-wasip1/release/*.wasm ./compiled/
2728

28-
## build-release: building the project in release mode
29-
build-release: bindings
30-
@$(CARGO) build --release
31-
3229
## update-submodules: update the git submodules
3330
update-submodules:
3431
@git submodule update --init --recursive
3532

3633
## clean: cleaning the project files
37-
clean:
34+
clean: clean-docker
3835
@forge clean
3936
@$(CARGO) clean
4037

38+
## clean-docker: remove unused docker containers
39+
clean-docker:
40+
@docker rm -v $(shell docker ps --filter status=exited -q) || true
41+
4142
## fmt: formatting solidity and rust code
4243
fmt:
4344
@forge fmt --check
@@ -46,15 +47,25 @@ fmt:
4647
## test: running forge and rust tests
4748
test:
4849
@forge test
49-
@$(CARGO) test
50+
@$(CARGO) test --manifest-path ./app/Cargo.toml
5051

5152
## setup: installing forge dependencies
5253
setup:
5354
@forge install
5455

56+
## start-all: starting anvil and WAVS with docker compose
57+
start-all: clean-docker
58+
@trap 'kill $(jobs -pr)' EXIT
59+
# running anvil out of compose is a temp work around for MacOS
60+
@anvil &
61+
@docker compose up
62+
@wait
63+
64+
_build_forge:
65+
@forge build
5566

5667
# Declare phony targets
57-
.PHONY: build build-release clean fmt bindings test
68+
.PHONY: build clean fmt bindings test
5869

5970
.PHONY: help
6071
help: Makefile

README.md

Lines changed: 30 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -18,117 +18,90 @@ Create a new project using this template:
1818

1919
```bash
2020
# If you don't have forge: `curl -L https://foundry.paradigm.xyz | bash`
21-
2221
forge init --template Lay3rLabs/wavs-foundry-template my-wavs
2322
```
2423

25-
## Testing
26-
27-
Given the repository contains both Solidity and Rust code, there's 2 different
28-
workflows.
29-
30-
### Setting up the Environment
31-
32-
Initialize the submodule dependencies:
24+
### Solidity
3325

3426
```bash
27+
# Initialize the submodule dependencies
3528
forge install
36-
```
37-
38-
Build the contracts:
3929

40-
```bash
30+
# Build the contracts
4131
forge build
42-
```
43-
44-
Run the tests:
4532

46-
```bash
33+
# Run the solidity tests. alias: `make test`
4734
forge test
4835
```
4936

50-
## Rust
37+
> You can also use `make build` to build the contracts, bindings, and components.
5138
52-
Rust bindings to the contracts can be generated via `forge bind`, which requires
53-
first building your contracts:
39+
## Rust
5440

5541
```bash
42+
# Generate new bindings from your contract(s)
5643
make bindings
57-
```
58-
59-
Then, you can run the tests:
6044

61-
```bash
62-
cargo test
45+
# Run rust tests
46+
make test
6347
```
6448

6549
## WAVS
6650

67-
Build the latest solidity:
51+
### Install the WAVS CLI
6852

6953
```bash
70-
make build
71-
```
72-
73-
Install the WAVS CLI:
74-
75-
```bash
76-
# MacOS: if you get permission errors: eval `ssh-agent -s`; ssh-add
54+
# MacOS: if you get permission errors: eval `ssh-agent -s` && ssh-add
7755
(cd lib/WAVS; cargo install --path ./packages/cli)
7856
```
7957

58+
### Start Anvil, WAVS, and Deploy Eigenlayer
59+
8060
```bash
61+
# copy over the .env file
8162
cp .env.example .env
8263

8364
# [!] Get your key from: https://openweathermap.org/
8465
# Update the WAVS_ENV_OPEN_WEATHER_API_KEY in the .env file with your key`
8566

86-
cp ./lib/WAVS/packages/wavs/wavs.toml .
87-
cp ./lib/WAVS/packages/cli/cli.toml .
88-
8967
# MacOS Docker:
9068
# Docker Engine -> Settings -> Resources -> Network -> 'Enable Host Networking'
9169
# or
9270
# brew install chipmk/tap/docker-mac-net-connect && sudo brew services start chipmk/tap/docker-mac-net-connect
93-
94-
# TODO: this is a temp workaround for MacOS (running anvil out of compose)
95-
anvil
96-
97-
docker compose up --build
71+
make start-all
9872
```
9973

100-
Deploy Eigenlayer and upload your WAVS Service contract
74+
### Upload your WAVS Service Manager
10175

10276
```bash
103-
docker_cmd="docker exec -it wavs bash -c"
104-
export CLI_EIGEN_CORE_DELEGATION_MANAGER=`${docker_cmd} 'jq -r .eigen_core.local.delegation_manager ~/wavs/cli/deployments.json' | tr -d '\r'`
105-
export CLI_EIGEN_CORE_REWARDS_COORDINATOR=`${docker_cmd} 'jq -r .eigen_core.local.rewards_coordinator ~/wavs/cli/deployments.json' | tr -d '\r'`
106-
export CLI_EIGEN_CORE_AVS_DIRECTORY=`${docker_cmd} 'jq -r .eigen_core.local.avs_directory ~/wavs/cli/deployments.json' | tr -d '\r'`
107-
export FOUNDRY_ANVIL_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
108-
77+
# Deploy (override: FOUNDRY_ANVIL_PRIVATE_KEY)
10978
forge script ./script/WavsServiceManager.s.sol --rpc-url http://localhost:8545 --broadcast
11079

111-
# set this in the your terminal from the script output
112-
export SERVICE_MANAGER_ADDRESS=0x851356ae760d987E095750cCeb3bC6014560891C
80+
# Grab deployed service manager address by name
81+
BROADCAST_FILE=./broadcast/WavsServiceManager.s.sol/31337/run-latest.json
82+
export SERVICE_MANAGER_ADDRESS=`jq -r '.transactions[] | select(.contractName == "WavsServiceManager") | .contractAddress' "${BROADCAST_FILE}"`
83+
echo "Service Manager Address: $SERVICE_MANAGER_ADDRESS"
11384
```
11485

115-
Build WAVS WASI component(s)
86+
### Build WASI components
87+
88+
> Install `cargo binstall cargo-component` if you have not already. -- https://github.com/bytecodealliance/cargo-component#installation
11689
11790
```bash
118-
# build all components/*
119-
# https://github.com/bytecodealliance/cargo-component#installation / cargo binstall cargo-component
12091
make wasi-build
12192

122-
# Verify execution works as expected without deploying
12393
# TODO: currently broken upstream
94+
# Verify execution works as expected without deploying
12495
# wavs-cli exec --component $(pwd)/compiled/eth_trigger_weather.wasm --input Nashville,TN
12596
```
12697

127-
Deploy service and verify with adding a task
98+
## Deploy Service and Verify
12899

129100
```bash
101+
# add read-write access
130102
sudo chmod 0666 .docker/cli/deployments.json
131103

104+
# Contract trigger function signature to listen for
132105
trigger_event=$(cast sig-event "NewTrigger(bytes)"); echo $trigger_event
133106

134107
service_info=`wavs-cli deploy-service --log-level=error --data ./.docker/cli --component $(pwd)/compiled/eth_trigger_weather.wasm \
@@ -139,10 +112,11 @@ service_info=`wavs-cli deploy-service --log-level=error --data ./.docker/cli --c
139112

140113
echo "Service info: $service_info"
141114

115+
# Submit AVS request -> chain
142116
SERVICE_ID=`echo $service_info | jq -r .service[0]`; echo "Service ID: $SERVICE_ID"
143117
wavs-cli add-task --input "Nashville,TN" --data ./.docker/cli --service-id ${SERVICE_ID}
144118

145-
# Where the call address is the service manager in ./.docker/cli/deployments.json
119+
# Grab data from the contract directly
146120
hex_bytes=$(cast decode-abi "getData(uint64)(bytes)" `cast call ${SERVICE_MANAGER_ADDRESS} "getData(uint64)" 1`)
147121
echo `cast --to-ascii $hex_bytes`
148122
```

foundry.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ libs = ['lib']
55
solidity_version = '0.8.22'
66
evm_version = 'shanghai'
77
via_ir = true
8+
fs_permissions = [{ access = "read", path = "./" },]
89

910
# See more config options https://github.com/foundry-rs/foundry/tree/master/config

script/WavsServiceManager.s.sol

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,38 @@ import {IDelegationManager} from
88
"@eigenlayer/middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol";
99
import {Quorum, StrategyParams} from "@eigenlayer/middleware/src/interfaces/IECDSAStakeRegistryEventsAndErrors.sol";
1010
import {IStrategy} from "@eigenlayer/middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
11+
import {stdJson} from "forge-std/StdJson.sol";
12+
13+
struct EigenContracts {
14+
address delegation_manager;
15+
address rewards_coordinator;
16+
address avs_directory;
17+
}
1118

1219
// forge script ./script/WavsServiceManager.s.sol --rpc-url http://localhost:8545 --broadcast --var-ir
1320
contract WavsServiceManagerScript is Script {
14-
address public delegation_manager = vm.envAddress("CLI_EIGEN_CORE_DELEGATION_MANAGER");
15-
address public rewards_coordinator = vm.envAddress("CLI_EIGEN_CORE_REWARDS_COORDINATOR");
16-
address public avs_directory = vm.envAddress("CLI_EIGEN_CORE_AVS_DIRECTORY");
21+
using stdJson for string;
1722

18-
uint256 privateKey = vm.envUint("FOUNDRY_ANVIL_PRIVATE_KEY");
23+
uint256 privateKey = vm.envOr(
24+
"FOUNDRY_ANVIL_PRIVATE_KEY", uint256(0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80)
25+
);
1926

2027
function setUp() public {}
2128

2229
function run() public {
2330
vm.startBroadcast(privateKey);
2431

25-
ECDSAStakeRegistry ecdsa_registry = new ECDSAStakeRegistry(IDelegationManager(delegation_manager));
32+
EigenContracts memory eigen = loadEigenContractsFromFS("deployments.json");
2633

27-
console.log("delegation_manager:", delegation_manager);
28-
console.log("rewards_coordinator:", rewards_coordinator);
29-
console.log("avs_directory:", avs_directory);
34+
ECDSAStakeRegistry ecdsa_registry = new ECDSAStakeRegistry(IDelegationManager(eigen.delegation_manager));
3035

31-
WavsServiceManager sm =
32-
new WavsServiceManager(avs_directory, address(ecdsa_registry), rewards_coordinator, delegation_manager);
36+
console.log("delegation_manager:", eigen.delegation_manager);
37+
console.log("rewards_coordinator:", eigen.rewards_coordinator);
38+
console.log("avs_directory:", eigen.avs_directory);
39+
40+
WavsServiceManager sm = new WavsServiceManager(
41+
eigen.avs_directory, address(ecdsa_registry), eigen.rewards_coordinator, eigen.delegation_manager
42+
);
3343

3444
IStrategy mockStrategy = IStrategy(address(0x1234));
3545
Quorum memory quorum = Quorum({strategies: new StrategyParams[](1)});
@@ -41,4 +51,19 @@ contract WavsServiceManagerScript is Script {
4151
console.log("ServiceManager:", address(sm));
4252
console.log("ecdssa_registry (deployed):", address(ecdsa_registry));
4353
}
54+
55+
function loadEigenContractsFromFS(string memory fileName) public view returns (EigenContracts memory) {
56+
string memory root = vm.projectRoot();
57+
string memory path = string.concat(root, "/.docker/cli/", fileName);
58+
string memory json = vm.readFile(path);
59+
60+
address dm = address(uint160(bytes20(json.readBytes(".eigen_core.local.delegation_manager"))));
61+
address rc = address(uint160(bytes20(json.readBytes(".eigen_core.local.rewards_coordinator"))));
62+
address avs = address(uint160(bytes20(json.readBytes(".eigen_core.local.avs_directory"))));
63+
64+
EigenContracts memory fixture =
65+
EigenContracts({delegation_manager: dm, rewards_coordinator: rc, avs_directory: avs});
66+
67+
return fixture;
68+
}
4469
}

0 commit comments

Comments
 (0)