Smart contracts that powers the PoS (proof-of-stake) based bridge mechanism for Matic Network
Polygon PoS (Proof-of-Stake) portal contracts
Smart contracts that powers the PoS (proof-of-stake) based bridge mechanism for Polygon Network.
Audits
Usage
Install package from NPM using
npm i @maticnetwork/pos-portal
Hardhat Build
Make sure you have installed NodeJS, NVM & NPM. Clone repository, switch to the required node version & install all dependencies
git clone https://github.com/0xPolygon/pos-portal
cd pos-portal
nvm i nvm use npm i npm run build
Hardhat Tests
After building as mentioned above, run the following command to run Hardhat tests
npm run test
Foundry Build
Make sure you have installed Foundry. Run the following command to run Foundry build
npm run generate:interfaces # generate interfaces with updated solc version
forge build
Foundry Tests
Modify the following in the .env file (create one if it doesn't exist)
# Infura API token - used for fork testing
INFURA_TOKEN=
Deployer private key - your private key, that has enough funds to deploy contracts on forked networks
PRIVATE_KEY=
After building as mentioned above, run the following command to run Foundry tests
forge test
Known Issues
ForkupgradeMPT.t.solcan take a while to complete. if it does, you can run the following command to skip it
forge test --no-match-test "SkipCI"
Other Build Options [Deprecated]
If you prefer not using docker for compiling contracts, consider setting docker: false in truffle-config.js.
// file: truffle-config.js
...
127| solc: { 128| version: '0.6.6', 129| docker: false, } ...
For deploying all contracts in pos-portal, we need to have at least two chains running --- simulating RootChain ( Ethereum ) & ChildChain ( Polygon ). There are various ways of building this multichain setup, though two of them are majorly used
- With
matic-cli - Without
matic-cli
matic-cli is a project, which makes setting up all components of Ethereum <-> Polygon multichain ecosystem easier. Three components matic-cli sets up for you
- Ganache ( simulating RootChain )
- Heimdall ( validator node of Polygon )
- Bor ( block production layer of Polygon i.e. ChildChain )
1. With matic-cli
Assuming you've installed matic-cli & set up single node local network by following this guide, it's good time to start all components seperately as mentioned in matic-cli README.
This should give you RPC listen addresses for both RootChain ( read Ganache ) & ChildChain ( read Bor ), which need to updated in pos-portal/truffle-config.js. Also note Mnemonic you used when setting up local network, we'll make use of it for migrating pos-portal contracts.
matic-cli generates ~/localnet/config/contractAddresses.json, given you decided to put network setup in ~/localnet directory, which contains deployed Plasma contract addresses. We're primarily interested in Plasma RootChain ( deployed on RootChain, as name suggests aka Checkpoint contract ) & StateReceiver contract ( deployed on Bor ). These two contract addresses need to be updated here.
You may not need to change stateReceiver field, because that's where Bor deploys respective contract, by default.
Plasma RootChain contract address is required for setting checkpoint manager in PoS RootChainManager contract during migration. PoS RootChainManager will talk to Checkpointer contract for verifying PoS exit proof.
// file: migrations/config.js
module.exports = { plasmaRootChain: '0x<fill-it-up>', // aka checkpointer stateReceiver: '0x0000000000000000000000000000000000001001' }
Now you can update preferred mnemonic to be used for migration in truffle config
// file: truffle-config.js
29| const MNEMONIC = process.env.MNEMONIC || '<preferred-mnemonic>'
Also consider updating network configurations for root & child in truffle-config.js
// make sure host:port of RPC matches properly
// that's where all following transactions to be sent
52| root: { host: 'localhost', port: 9545, network_id: '*', // match any network skipDryRun: true, gas: 7000000, gasPrice: '0' }, child: { host: 'localhost', port: 8545, network_id: '*', // match any network skipDryRun: true, gas: 7000000, gasPrice: '0' 67| },
Now start migration, which is 4-step operation
Migration Step | Effect :-- | --: migrate:2 | Deploys all rootchain contracts, on Ganache migrate:3 | Deploys all childchain contracts, on Bor migrate:4 | Initialises rootchain contracts, on Ganache migrate:5 | Initialises childchain contracts, on Bor
# assuming you're in root of pos-portal
npm run migrate # runs all steps
You've deployed all contracts required for pos-portal to work properly. All these addresses are put into ./contractAddresses.json, which you can make use of for interacting with them.
If you get into any problem during deployment, it's good idea to take a look attruffle-config.jsorpackage.json--- and attempt to modify fields need to be modified.
Migration files are kept here ./migrations/{1,2,3,4,5}*.js
2. Without matic-cli
You can always independently start a Ganache instance to act as RootChain & Bor node as ChildChain, without using matic-cli. But in this case no Heimdall nodes will be there --- depriving you of StateSync/ Checkpointing etc. where validator nodes are required.
Start RootChain by
npm run testrpc # RPC on localhost:9545 --- default
Now start ChildChain ( requires docker )
npm run bor # RPC on localhost:8545 --- default
If you ran a bor instance before, a dead docker container might still be lying around, clean it using following command:
npm run bor:clean # optional
Run testcases
npm run test
Deploy contracts on local Ganache & Bor instance
npm run migrate
This should generate ./contractAddresses.json, which contains all deployed contract addresses --- use it for interacting with those.
Production
Use this guide for deploying contracts in Ethereum Mainnet.
- Moonwalker needs rabbitmq and local geth running
docker run -d -p 5672:5672 -p 15672:15672 rabbitmq:3-management
npm run testrpc
- Export env vars
export MNEMONIC=
export FROM=
export PROVIDER_URL=
export ROOTCHAINID=
export CHILDCHAINID=
export PLASMAROOTCHAIN=
export GAS_PRICE=
- Compile contracts
npm run template:process -- --root-chain-id $ROOTCHAINID --child-chain-id $CHILDCHAINID
npm run build
- Add root chain contract deployments to queue
npm run truffle exec moonwalker-migrations/queue-root-deployment.js
- Process queue (rerun if interrupted)
node moonwalker-migrations/process-queue.js
- Extract contract addresses from moonwalker output
node moonwalker-migrations/extract-addresses.js
- Deploy child chain contracts
npm run truffle -- migrate --network mainnetChild --f 3 --to 3
- Add root chain initializations to queue
node moonwalker-migrations/queue-root-initializations.js
- Process queue (rerun if interrupted)
node moonwalker-migrations/process-queue.js
- Initialize child chain contracts
npm run truffle -- migrate --network mainnetChild --f 5 --to 5
- Register State Sync
- Register RootChainManager and ChildChainManager on StateSender
- Set stateSenderAddress on RootChainManager
- Grant STATESYNCERROLE on ChildChainManager
Command scripts (Management scripts)
npm run truffle exec scripts/update-implementation.js -- --network <network-name> <new-address>
Transfer proxy ownership and admin role
Set list of contract addresses and new owner address in6changeowners.js migration script
Set MNEMONIC and API_KEY as env variables
```bash
npm run change-owners -- --network