An implementation of the EigenLayer Incredible Squaring AVS in Python. This repository showcases how to use EigenLayer Python SDK to build an Autonomous Verifiable Service (AVS) in Python.
Foundry is required to build the AVS smart contracts, run a local Anvil chain, deploy contracts to Anvil, and test the Python AVS against the local setup.
Install Foundry:
curl -L https://foundry.paradigm.xyz | bash
foundryup
Python 3.11+ with pip is required to run the AVS binaries.
Node.js 20+ with npm is required to build and deploy the subgraph to a local Graph Node.
Docker is required to run the Graph Node and IPFS services using Docker Compose, and to run the Docker-based tests.
make build-docker
make test-docker
Create a virtual environment and install Python dependencies using:
python3 -m venv .venv
source .venv/bin/activate
pip install .
For development (includes linting, type checking, and formatting tools) install the repository using:
pip install -e ".[dev]"
Install latest version of node and required dependencies for deploying subgraph:
curl -o- https://github.com/nvm-sh/nvm/v0.40.3/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 22
cd avs-subgraph
npm i -g @graphprotocol/graph-cli@latest
npm i
This simple session illustrates the basic flow of the AVS. The makefile commands are hardcoded for a single operator, but it's however easy to create new operator config files, and start more operators manually (see the actual commands that the makefile calls).
Start anvil in a separate terminal:
anvil --host 0.0.0.0
Note: Using --host 0.0.0.0
enables the subgraph node to connect to the anvil chain.
Build the contracts:
make build-contracts
Deploy contracts, set UAM permissions, and create a quorum in a single command:
make deploy-all
Start the graph node:
make start-graph-node
Note: To start the graph node from scratch, remove the data
folder inside the avs-subgraph
using rm avs-subgraph/data -rf
before starting the subgraph.
Deploy the subgraph:
make deploy-subgraph
Start the aggregator:
make start-aggregator
Register the operator with eigenlayer and incredible-squaring, and then start the process:
make start-operator
By default, the start-operator
command will also register the operator.
To disable this, set register_operator_on_startup
to false
in opeartor yaml
file in the config-files
.
The operator can be manually registered by running make cli-setup-operator
.
The operator will produce an invalid result 10 times out of 100, as it is set in the times_failing
field of the config.
These failures result in slashing once they're challenged.
To see this in action, start the challenger with:
make start-challenger
make create-avs-distributions-root
make claim-distributions
make claimer-account-token-balance
make create-operator-directed-distributions-root
make claim-distributions
make claimer-account-token-balance
- Aggregator: Publishes new tasks, aggregates signed responses, and submits them on-chain.
- Operator: Listens for tasks, computes square, signs result, and submits to aggregator.
- Challenger: Verifies correctness of submitted results and challenges if incorrect.
Each task requires computing x^2
for a given x
. The aggregator checks that BLS signature quorum thresholds are met before submitting the aggregated result.
Run integration tests locally:
source .venv/bin/activate
pytest tests/ -v
Run code linting with flake8:
make lint
Run type checking with mypy:
make mypy
Format code with black and isort:
make format
Check if code is properly formatted:
make format-check
Run all code quality checks at once:
make check-all