- Clone with --recursive or remember to pull the submodules for solidity dependencies
-
Copy
.env.example
to.env
and set the right vars -
Install WAVS natively
Docker won't work out of the box here because we need WAVS to listen to a local Cosmos chain we'll be running
git clone https://github.com/Lay3rLabs/WAVS.git ~/WAVS
cd ~/WAVS && just install-native ~/wavs-config ~/wavs-data
- Build all the contracts and components
just build
That's it!
- Start the backend
just start-backend
tip: wait until these are ready before proceeding:
- Hitting http://localhost:8000/info shows a list of operators
- Hitting http://localhost:26657/status shows a valid cosmos status
This may take some time if you've never started the backend before, but subsequent start-ups should be quick.
- Deploy contracts and services
just deploy
This may take some time if you've never deployed before, but subsequent deployments should be quick.
- Bridge assets
just bridge
You'll see it do some stuff and then print out your balance.
- Stop the backend
just stop-backend
Almost everyting is in the justfiles (using wavs-cli
and forge
to do the heavy lifting).
A minimal cosmos client is in cosmos-client
Overall flow when running just bridge
is:
- (user action) sending some
ulayer
to the Cosmos chain - (cosmos chain) emits an event
- (wavs) picks up the event
- (wavs) passes the event data to the component
- (component) extracts the amount and recipient from the event data
- (component) encodes the info into an ethereum-friendly type (shared at compiletime w/ alloy sol! macro)
- (wavs) signs this output from the component, submits it to eigenlayer contract
- (ethereum: Eigenlayer-aware LayerServiceManager) verifies the operator and signature, calls LayerServiceHandler
- (ethereum: Vanilla LayerServiceHandler + ERC20) extracts the data, mints tokens
The only thing copy/pasted from WAVS repo is the solidity interfaces.
For the sake of keeping the example brief, this does not implement any security measures to prevent anyone from minting. That could easily done in a number of ways (e.g. requiring that the caller be the service manager, signing with a secret on the component side, etc.), but would distract from the point of this example.
If you're using this repo for mainnet... erm.. don't :P