A CLI to setup Matic network
Testing Toolkit
🏗 A set of CLIs, tools and tests to set up, manage and operate Polygon devnets.
The Testing Toolkit is built on top of express-cli, an extension of matic-cli which uses terraform to deploy, test and monitor any devnet on AWS/GCP stacks from any local system.
It currently supports only devnets running v0.3.x stacks.
The express-cli interacts with terraform to create a fully working setup on AWS/GCP. In case the infrastructure already exists, matic-cli can be used as a standalone tool to deploy Polygon stacks on pre-configured VMs.
Please, refer to the section of this file you are more interested in (express-cli or matic-cli)
Table of contents
express-cli
Requirements
To use the express-cli you have to execute the following steps.
- install aws cli or install gcloud tool
- install terraform on your local machine
- use nvm to switch to the proper
nodeversion,v18.19.0,
nvm use from the root folder
- install
express-cliandmatic-clilocally with commandnpm i - generate a keypair on AWS EC2 (in the same region being used, currently
eu-west-1by default and download its certificate locally (.pemfile). If you are on GCP, you can use your existing keypair or usessh-keygento generate. Check the GCP guide. - copy
secret.tfvars.exampletosecret.tfvarwith commandcp secret.tfvars.example secret.tfvarsand check the commented file for details - If you are a Polygon employee, connect to the company VPN
- modify
secret.tfvarwith addresses of the allowed IPs (as specified insecret.tfvars.examplefile) - copy
.env.exampleto.envwith commandcp .env.example .envand check the heavily commented file for details. If you're using GCP, you can ignore AWS specific terraform variables and vice versa. - make sure
PEMFILEPATHpoints to a correct AWS key certificate, the one you downloaded in the previous steps - define the number of nodes (
TFVARVALIDATORCOUNTandTFVARSENTRYCOUNT) and adjust theDEVNETBORUSERS
- use
TFVARDOCKERZIED=noto have one VM per node, otherwise the stack will run on one VM only in a dockerized environment - (optional) replace
TFVARVM_NAMEwith your own identifier (it can be any string, default is "polygon-user") - (optional) replace
TFVARDISKSIZEGBwith your preferred disk size in GB (default is 100 GB) VERBOSE=trueprints logs from the remote machines. If set tofalse, onlyexpress-cliandmatic-clilogs will
Auth Configuration
As a prerequisite, you need to configure authentication on aws This will create the folder ~/.aws in your system To do so, please run
aws configure sso
This command will interactively ask for some configs If you are a Polygon employee, please use the following
- SSO session name: leave empty
- SSO start URL: https://0xpolygon.awsapps.com/start/#/
- SSO region: eu-west-1
In case there are multiple accounts available to you, please select
posv1-devnet
Then, the command will ask for other configs, please use
- CLI default client Region: eu-west-1
- CLI default output format: json
- CLI profile name: default
CLI profile name: default, as used by terraform in express-cli (for more context see this)
Here an output example
SSO session name (Recommended):
WARNING: Configuring using legacy format (e.g. without an SSO session).
Consider re-running "configure sso" command and providing a session name.
SSO start URL [None]: https://0xpolygon.awsapps.com/start/#/
SSO region [None]: eu-west-1
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:
https://device.sso.eu-west-1.amazonaws.com/
Then enter the code:
<CODE-HERE>
There are 2 AWS accounts available to you.
Using the account ID <ACCOUNT_ID> The only role available to you is: <AWSRole> (<AWSROLEID>) Using the role name "<AWS_ROLE>" CLI default client Region [None]: eu-west-1 CLI default output format [None]: json CLI profile name [<PROFILENAMEAND_ID>]: default
To use this profile, specify the profile name using --profile, as shown:
aws s3 ls --profile default
Now you can log into aws by running the following command. It needs to be executed every time the token expires.
aws sso login
Congrats! You're all set to use express-cli commands.
If you are using Google cloud platform, you need to configure authentication on gcloud.
If you have downloaded the service account credentials, you can use the GOOGLEAPPLICATIONCREDENTIALS environment variable to provide the location of that credential JSON file.
gcloud auth application-default login
OR
export GOOGLE_APPLICATI
Commands
Instructions to run express-cli. For the list of commands, please run express-cli --help First off, you need to --init terraform on your local machine, by executing the following command.
./bin/express-cli.js --init <aws|gcp>
devnet-<id> where id is a monotonically
increasing count for the devnets. Once created, you can cd deployments/devnet-<id> and run the other commands.
This allows you to work with multiple devnets at once.
Then, a remote devnet can be created with the --start command, as follows.
- You should specify the cloud provider. Currently the supported values are aws and gcp.
../../bin/express-cli.js --start
.env.devnet<id> file
- --start command can be used also to target an existing AWS setup. If changes to .env.devnet<id> file are detected, the
previous devnet will be destroyed and a new one created, reusing the same AWS VMs
To destroy the remote devnet, you can execute the --destroy command.
../../bin/express-cli.js --destroy
The express-cli also comes with additional utility commands, listed below. Some of them are only available for non-dockerized devnets.
../../bin/express-cli.js --update-all [index]
heimdall,bor and erigon branches defined as HEIMDALLBRANCH, BORBRANCH and ERIGON_BRANCH in .env. devnet<id> file, pulls relative changes and restarts those services on the remote machines. If an integer index is used, the job will be performed only on the VM corresponding to that index. For example if the devnet consists of 2 bor and erigon nodes, then the indices for bor machines would be 0 and 1 and for erigon it'll be 2 and 3.
../../bin/express-cli.js --update-bor [index]
bor branch defined as BOR_BRANCH in .env.devnet<id> file, pulls relative changes and restarts it on
the remote machines. If an integer index is used, the job will be performed only on the VM corresponding to that index.
../../bin/express-cli.js --update-erigon [index]
erigon branch defined as ERIGON_BRANCH in .env.devnet<id> file, pulls relative changes and restarts it on
the remote machines. If an integer index is used, the job will be performed only on the VM corresponding to that index. For example, if the devnet consists of 2 bor and erigon nodes and you want to target the first erigon node, index will be 2.
../../bin/express-cli.js --update-heimdall [index]
heimdall branch defined as HEIMDALL_BRANCH in .env.devnet<id> file, pulls relative changes and restarts it on
the remote machines. If an integer index is used, the job will be performed only on the VM corresponding to that
index. For example if the devnet consists of 2 bor and erigon nodes, then the indices for bor machines would be 0 and 1 and for erigon it'll be 2 and 3.
../../bin/express-cli.js --restart-all [index]
bor, erigon and heimdall on all the remote machines. If an integer index is used, the job will be performed
only on the VM corresponding to that index. For example if the devnet consists of 2 bor and erigon nodes, then the indices for bor machines would be 0 and 1 and for erigon it'll be 2 and 3.
../../bin/express-cli.js --restart-bor [index]
bor on all the remote machines. If an integer index is used, the job will be performed only on the VM
corresponding to that index.
../../bin/express-cli.js --restart-erigon [index]
erigon on all the remote machines. If an integer index is used, the job will be performed only on the VM
corresponding to that index. For example if the devnet consists of 2 bor and erigon nodes and you wanted to target the first erigon node, index will be 2.
../../bin/express-cli.js --restart-heimdall [index]
heimdall on all the remote machines. If an integer index is used, the job will be performed only on
the VM corresponding to that index. For example if the devnet consists of 2 bor and erigon nodes, then the indices for bor machines would be 0 and 1 and for erigon it'll be 2 and 3.
../../bin/express-cli.js --cleanup
anvil, bor, heimdall and bridge, redeploys all the contracts and restarts all the services
The express-cli also provides additional testing commands, listed here.
../../bin/express-cli.js --send-state-sync
state-sync transaction on the remote network
../../bin/express-cli.js --send-staked-event [validatorID]
Staked transaction on the remote network and adds a new validator.
../../bin/express-cli.js --send-stakeupdate-event [validatorID]
StakeUpdate transaction on the remote network and increase stake of 1st validator by 100 MATIC.
../../bin/express-cli.js --send-signerchange-event [validatorID]
SignerChange transaction on the remote network and changes the signer of the 1st validator.
../../bin/express-cli.js --send-topupfee-event [validatorID]
TopUpFee transaction on the remote network and adds balance/heimdallFee for the first validator on Heimdall.
../../bin/express-cli.js --send-unstakeinit-event [validatorID]
UnstakeInit transaction on the remote network and removes the validator from validator-set. validatorID can be used to specify the validator to be removed. If not specified, the first validator will be removed.
../../bin/express-cli.js --send-gov-tests
../../bin/express-cli.js --send-auth-bank-tests
../../bin/express-cli.js --monitor [exit]
--send-state-sync hasn't been used before, only checkpoints will be detected. Monitor the setup.
If exit string is passed the process terminates when at least one stateSync and one checkpoint are detected.
../../bin/express-cli.js --instances-stop
../../bin/express-cli.js --instances-start
../../bin/express-cli.js --stress [fund]
fund is needed when stress tests are ran for the first time,
to fund the accounts
../../bin/express-cli.js --setup-datadog
DDAPIKEY env var is required for this.
../../bin/express-cli.js --setup-ethstats
../../bin/express-cli.js --chaos [intensity]
intensity parameter is optional and can be set from 1 to 10. If not set, 5 is used.
../../bin/express-cli.js --rewind [numberOfBlocks]
128). Default numberOfBlocks value is 100.
../../bin/express-cli.js --eip-1559-test [index]
../../bin/express-cli.js --ssh-key-add
../../bin/express-cli.js --ssh-key-des [keyName]
keyName. The key gets deleted remotely from aws or gcp, cancelled from the authorized ssh keys of the devnet's machines and removed from local devnet folder.
../../bin/express-cli.js --reorg-start [split]
../../bin/express-cli.js --reorg-stop
../../bin/express-cli.js --shadow-fork [blockNumber]
../../bin/express-cli.js --rpc-test
RPC_URL and MNEMONIC set
- MNEMONIC need funds on its first derivation account (m/44'/60'/0'/0/0) to deploy a small contract
- Execute a suite of RPC tests against the provided RPC URL, agnostic to the environment. The tests are capable of running on any network, including devnet, testnet (e.g., Amoy/Mumbai), and mainnet, with the only requirement being that the necessary funds are available in the corresponding account on the network
../../bin/express-cli.js --relay
../../bin/express-cli.js --fund-anvil-accounts
Note: to allow express-cli to clone private repos, make sure the git configs in the .env file looks like the following (example for BOR_REPO)
# BOR_REPO="https://<username>:<token>@github.com/<username>/<repo>.git" # example of private repo URL
Milestone tests
The express-cli can also be used to perform few simulation based tests for the upcoming milestone feature. Please refer to the steps and requirements mentioned over here for running the tests.
matic-cli
matic-cli has to be installed on a ubuntu VM (host) and - through a config file - it will point to other VMs' IPs (remotes).
- Host machine will run a Polygon node (
borandheimdall) and a layer 1 node (anvil) - Remote machines will only run a Polygon node each
Requirements
Please, make sure to install the following software/packages on the VMs.
Ubuntu
- Build Essentials (host and remotes)
sudo apt update --yes && sudo apt install --yes build-essential
- Go 1.18+ (host and remotes)
wget https://raw.githubusercontent.com/0xPolygon/node-ansible/master/go-install.sh \
&& bash go-install.sh --remove \
&& bash go-install.sh
- Rabbitmq (host and remotes)
sudo apt install --yes rabbitmq-server
- Docker (host and remotes, only needed in case of a docker setup)
- Node v18.19.0 (only host)
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash \
&& source ~/.bashrc \
&& nvm install 18.19.0 \
&& node --version
- Npm (only host)
sudo apt update --yes && sudo apt install --yes npm
- Python 3 (only host)
sudo apt install python3 python3-pip --yes && alias python="/usr/bin/python3"
- Solc v0.5.17 and 0.6.12 (only host)
sudo pip install solc-select
solc-select install 0.5.17
solc-select install 0.6.12
solc-select use 0.5.17
- Anvil CLI (only host)
curl -L https://foundry.paradigm.xyz | bash && export PATH="$HOME/.foundry/bin:$PATH" >> ~/.bashrc && source ~/.bashrc && foundryup
MacOS
- Build Essentials (host and remotes)
xcode-select --install
- Go 1.18+ (host and remotes)
curl -O https://raw.githubusercontent.com/0xPolygon/node-ansible/master/go-install.sh
bash go-install.sh --remove
bash go-install.sh
- Rabbitmq (host and remotes)
brew install rabbitmq
- Docker (host and remotes, only needed in case of a docker setup)
- Node v18.19.0 (only host)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash \
&& nvm install 18.19.0 \
&& node --version
- Python 3 (only host)
brew install pyenv
pyenv install 3.13.2
pyenv global 3.13.2
python3 --version
pyenv exec python3 -m ensurepip --default-pip
python3 -m pip install --upgrade pip
- Solc v0.5.17 and 0.6.12 (only host)
pip3 install solc-select
solc-select install 0.5.17
solc-select install 0.6.12
solc-select use 0.5.17
- Anvil CLI (only host)
curl -L https://foundry.paradigm.xyz | bash && export PATH="$HOME/.foundry/bin:$PATH" >> ~/.bashrc && source ~/.bashrc && foundryup
Usage
On the host machine, please run
cd \
&& git clone https://github.com/0xPolygon/matic-cli.git \
&& cd matic-cli \
&& npm install
Local dockerized network
Install the required software on your machine (see Requirements).
Adjust the docker configs based on your setup, and run
mkdir devnet \
&& cd devnet \
&& ../bin/matic-cli.js setup devnet --config ../configs/devnet/docker-setup-config.yaml | tee setup.log
This will create and spin up the devnet. The process will take some time, until this log shows up
DONE Devnet is ready
Once the setup is done, use the aggregated script for local docker deployment
bash ../util-scripts/docker/devnet_setup.sh
To verify the deployment, run the smoke test to ensure everything is working properly. The script usually takes around 6mins to complete.
bash ../util-scripts/docker/smoke_test.sh
To add funds to the signer's account you can execute the following script. This step is optional, as all existing signers already have sufficient funds.
bash ../util-scripts/docker/fundanvilaccounts.sh
Logs will be stored under logs/ folder
Note: in case of docker setup, we have provided some additional scripts which might be helpful.
Remote network
Adjust the remote configs and run
../bin/matic-cli.js setup devnet --config ../configs/devnet/remote-setup-config.yaml | tee setup.log
Alternatively, this step can be executed interactively with
../bin/matic-cli.js setup devnet --interactive
Once the setup is done, follow these steps for remote deployment In this case, the stack is already running, you would just need to deploy/sync some contracts, as follows:
- Move to devnet folder
cd matic-cli/devnet
- Deploy contracts on Child chain
bash anvil-deployment-bor.sh
- Sync contract addresses to Main chain
bash anvil-deployment-sync.sh
Clean setup
Stop all services, remove the matic-cli/devnet folder, and you can start the process once again
Notes
Install the required software on your machine (see Requirements).
Adjust the docker configs based on your setup, and run
- The anvil URL hostname will be used for anvil
http://<host-machine-ip>:9545 - Make sure that the host machine has access to remote machines for transferring the data
eval "$(ssh-agent -s)"
ssh-add <.pem file>
- We have provided the default config values here to ensure smooth functioning of the process
express-cli, hence they should not be deleted nor any modification remotely pushed
Therefore, they are under .gitignore, and in case you do not want those changes to be reflected in your local git,
you can use the commands
git update-index --assume-unchanged configs/devnet/remote-setup-config.yaml
git update-index --assume-unchanged configs/devnet/docker-setup-config.yaml
to undo, please use
git update-index --no-assume-unchanged configs/devnet/remote-setup-config.yaml
git update-index --no-assume-unchanged configs/devnet/docker-setup-config.yaml
License
MIT