Code Monkey home page Code Monkey logo

pos-portal's Introduction

Matic PoS (Proof-of-Stake) portal contracts

Build Status

Smart contracts that powers the PoS (proof-of-stake) based bridge mechanism for Matic Network.

Audits

Usage

Install package from NPM using

npm i @maticnetwork/pos-portal

Develop

Make sure you've NodeJS & NPM installed

user:pos-portal anjan$ node --version
v12.18.1

user:pos-portal anjan$ npm --version
6.14.5

Clone repository & install all dependencies

git clone https://github.com/maticnetwork/pos-portal
cd pos-portal

npm i

Compile all contracts

npm run template:process
npm run build

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

  1. With matic-cli
  2. 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 )

You may want to check matic-cli.


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 at truffle-config.js or package.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.

  1. Moonwalker needs rabbitmq and local geth running
docker run -d -p 5672:5672 -p 15672:15672 rabbitmq:3-management
npm run testrpc
  1. Export env vars
export MNEMONIC=
export FROM=
export PROVIDER_URL=
export ROOT_CHAIN_ID=
export CHILD_CHAIN_ID=
export PLASMA_ROOT_CHAIN=
export GAS_PRICE=
  1. Compile contracts
npm run template:process -- --root-chain-id $ROOT_CHAIN_ID --child-chain-id $CHILD_CHAIN_ID
npm run build
  1. Add root chain contract deployments to queue
npm run truffle exec moonwalker-migrations/queue-root-deployment.js
  1. Process queue (rerun if interrupted)
node moonwalker-migrations/process-queue.js
  1. Extract contract addresses from moonwalker output
node moonwalker-migrations/extract-addresses.js
  1. Deploy child chain contracts
npm run truffle -- migrate --network mainnetChild --f 3 --to 3
  1. Add root chain initializations to queue
node moonwalker-migrations/queue-root-initializations.js
  1. Process queue (rerun if interrupted)
node moonwalker-migrations/process-queue.js
  1. Initialize child chain contracts
npm run truffle -- migrate --network mainnetChild --f 5 --to 5
  1. Register State Sync
  • Register RootChainManager and ChildChainManager on StateSender
  • Set stateSenderAddress on RootChainManager
  • Grant STATE_SYNCER_ROLE 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 in 6_change_owners.js migration script
Set MNEMONIC and API_KEY as env variables

npm run change-owners -- --network <network-name>

pos-portal's People

Contributors

arthcp avatar atvanguard avatar ayushkaul avatar dependabot[bot] avatar gretzke avatar itzmeanjan avatar jdkanani avatar nachomazzara avatar onigiri-x avatar qedk avatar sanchaymittal avatar simondos avatar wschwab avatar zeroekkusu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pos-portal's Issues

How to Register RootChainManager and ChildChainManager on StateSender?

In Step 11 Register State Sync

Register RootChainManager and ChildChainManager on StateSender
Set stateSenderAddress on RootChainManager
Grant STATE_SYNCER_ROLE on ChildChainManager

Can anyone explain how to Register RootChainManager and ChildChainManager on StateSender?

Here is the StateSender contract
`contract DummyStateSender is IStateSender {
/**
* @notice Event emitted when when syncState is called
* @dev Heimdall bridge listens to this event and sends the data to receiver contract on child chain
* @param id Id of the sync, increamented for each event in case of actual state sender contract
* @param contractAddress the contract receiving data on child chain
* @param data bytes data to be sent
*/
event StateSynced(
uint256 indexed id,
address indexed contractAddress,
bytes data
);

/**
 * @notice called to send data to child chain
 * @dev sender and receiver contracts need to be registered in case of actual state sender contract
 * @param receiver the contract receiving data on child chain
 * @param data bytes data to be sent
 */
function syncState(address receiver, bytes calldata data) external override {
    emit StateSynced(1, receiver, data);
}

}`

Allow deposit by someone who is not a token owner

Motivation

In our app we want to provide people a better user experience when they deposit their tokens to polygon.
That is why we want RootChainManager#depositFor to be callable by an address that is not a token owner (like approved or approved for all).

Problem

That is not currently possible with MintableERC721Predicate (I didn't check others, but it is probably the same issue there).

Here is why:
RootChainManager always uses _msgSender as a depositor:


depositor is always passed as a first argument to ERC721#safeTransferFrom which should always be a token owner:
IMintableERC721(rootToken).safeTransferFrom(depositor, address(this), tokenId);

Solution

Use ERC721#ownerOf instead of depositor when calling ERC721#safeTransferFrom.

If that is not acceptable, can you explain a motivation of this limitation?

API for Polygon Bridge Status

This is a request to create an API to get the Polygon Bridge status. When it is down, we have no way to know it is down and to notify our users.

Not receiving MATIC staking rewards

Not sure if this is the right place to create this issue but Since 3 days i have not receiving my staking rewards and same for everyone in the community. When i check the staking checkpoint it says last checkpoint was done on march 10

Passing NFT arbitrary data from L1 -> L2 ?

This might sounds weird but..
Let's say I have a random number already generated and associated to my NFT in L1.
That number influences how tokenURI() is returned.
So I wanna make sure that my bridged NFT in L2 act the same.


Looking at ERC721Predicate


It seems like ERC721Predicate.lockTokens() only assume that depositData are tokenId(s)


I saw the ability to send meta data back from L2 -> L1 (here: #67)
But not the other way around. Any suggestion? 🙏🏼

PREDICATE_ROLE assignment missing in root/RootToken/DummyMintableERC20.sol? Deployment documentation needed.

Is there any documentation for deploying mintable ERC20 on both chains?

My intuition of the procedure would be the following:

  1. Deploy root/RootToken/DummyMintableERC20.sol on Ethereum
  2. Deploy child/ChildToken/ChildMintableERC20.sol on Matic
  3. Requesting mapping on https://mapper.matic.today/

However how is the rootChainManager supposed to mint tokens if it doesn't have the PREDICATE_ROLE? Shouldn't there be another PREDICATE_ROLE assignment in the constructor or is an additonal external call needed?

Validate Permission Before BatchWithdraw

Hey guys, im new to the whole debugging .Sol so forgive me if im wrong rsrsr :)
but was checking this contract's code today and got the feeling that the code could be incorrectly allowing the ChildChainManager to withdraw funds on behalf of users
without their permission. The issue is in the deposit function, where the withdrawnTokens mapping is being set to false
for each deposited token, but this value is never checked again before the tokens are withdrawn in the withdrawBatch
function.

To fix this issue, the withdrawBatch function should check the withdrawnTokens mapping before allowing the tokens to
be withdrawn. For example, the code could be changed to this:

    function withdrawBatch(uint256[] calldata tokenIds) external {
        require(_msgSender() == _getCaller(), "ChildMintableERC721: INVALID_CALLER");

        // limit batching of tokens due to gas limit restrictions
        require(tokenIds.length <= BATCH_LIMIT, "ChildMintableERC721: BATCH_LIMIT_EXCEEDED");

        for (uint256 i = 0; i < tokenIds.length; i++) {
            uint256 tokenId = tokenIds[i];
            require(_hasToken(tokenId), "ChildMintableERC721: TOKEN_NOT_FOUND");

            // check if the token has already been withdrawn
            require(!withdrawnTokens[tokenId], "ChildMintableERC721: TOKEN_ALREADY_WITHDRAWN");

            withdrawnTokens[tokenId] = true;
            _burn(tokenId);
        }

        emit WithdrawnBatch(_msgSender(), tokenIds);
    }

best of Luck to Yall :)

Implement EIP-1271 isValidSignature to allow smart contract wallets to interact with Polygon PoS

Smart contract wallets (i.e., Argent, Dharma) are becoming ever more popular yet they do not possess private keys and therefore can not directly sign messages. This means that valid transactions from smart contract wallets are recognized as invalid by the current method Polygon PoS uses to determine whether a transaction is valid.

I'd like to suggest implementing the EIP-1271 isValidSignature method in addition to traditional verify method currently used which only works for EOAs. For example here:

function verify(
address signer,
MetaTransaction memory metaTx,
bytes32 sigR,
bytes32 sigS,
uint8 sigV
) internal view returns (bool) {
require(signer != address(0), "NativeMetaTransaction: INVALID_SIGNER");
return
signer ==
ecrecover(
toTypedMessageHash(hashMetaTransaction(metaTx)),
sigV,
sigR,
sigS
);
}

(There are also other places where verify is used, but I'm not familiar with the codebase enough to know where the change would need to take place)

Further exaggerating this issue IMHO, is that the current Polygon PoS functionality allows one to deposit funds from their smart contract wallet (i.e., Argent) successfully without issue nor warning, but once deposited, the funds remain locked due to the lack of implementation of EIP-1271. I know personally, because I just did this a few days ago to test out Polygon, and now those funds are locked on Polygon PoS with no way to withdraw nor send (Polygon support ticket #4393 open). I'm probably not the only one who has done this so far, and with growing usage of Polygon and smart contract wallets, I certainly won't be the last one to do this.

Another option would be to only allow for smart contract accounts to withdraw their funds back to mainnet L1 to their specific account. This may be an acceptable option if the complexity to implement EIP-1271 for all transaction types would be too high.

Thanks for your time. Feedback welcome!

Resources:
https://eips.ethereum.org/EIPS/eip-1271
https://docs.walletconnect.org/smart-wallets
https://docs.argent.xyz/wallet-connect-and-argent

Questions on Polygon mintable assets

I have several questions on Polygon mintable assets, based on the templates in this repository:

https://github.com/maticnetwork/pos-portal/blob/master/flat/ChildMintableERC20.sol
https://github.com/maticnetwork/pos-portal/blob/master/flat/DummyMintableERC20.sol

The documentation here does not address these questions.

(1) Should the name (ticker) of the token on the Polygon network be the same as the name of the token on Ethereum mainnet? So if my Ethereum ERC20 token is called XYZ, should the Polygon version be called just XYZ, or should it be called wXYZ?

(2) Why does the ChildMintableERC20.withdraw​ function have no access controls? I realize if a user calls this, it will only lose them tokens, but shouldn't you limit access to calling this function to only a Polygon router? Otherwise maybe a user can burn tokens early, which will make the router fail when trying to move tokens between chains. Who knows, it could trigger some security vulnerability. All router-specific functions should be locked down and limited so that only the router can call them.

(3) Why does the ChildMintableERC20.deposit function take an argument bytes calldata depositData​, which has to be decoded through abi.decode​? Why isn't the parameter decoded before it is passed to this function?

(4) Why does the mint​ function require the role DEFAULT_ADMIN_ROLE​, while deposit​ requires DEPOSITOR_ROLE​? In practice, is it only one router contract that has both roles? Your documentation on mintable assets does not talk about what the DEFAULT_ADMIN_ROLE​ role is, or which router contract should be assigned this role.

(5) Your contract DummyMintableERC20​ has a function mint(address user, uint256 amount)​ which has the same signature as the function of the same name in ChildMintableERC20​. However, the former takes role PREDICATE_ROLE​ and the latter takes role DEFAULT_ADMIN_ROLE​. If I want to deploy the same exact contract to Ethereum mainnet and Polygon, does this mean this function needs to be callable by two different contracts, one for each of the two roles?

Wrong implementation of the EIP712 signatures

Hello, I am having problems to make EIP3009 from usdc polygon pos to work and it seems it uses the contracts from this repo.

It seems the EIP712 is wrong implemented: https://github.com/maticnetwork/pos-portal/blob/master/contracts/common/EIP712Base.sol#L36

First, the order from the domain separator should be in the order they give you here: https://eips.ethereum.org/EIPS/eip-712

Moreover the calculation of the EIP712_DOMAIN_TYPEHASH is wrong. We are using salt but we are not encoding any salt at all. EIP712Domain(string name,string version,address verifyingContract,bytes32 salt) this gives problems when you want to calculate the signature with standards like signTypedData from metamask.

Add NewHeaderBlock event to MockCheckpointManager and ICheckpointManager

Some operations require us to track NewHeaderBlock event of RootChain contracts. That is possible to do. However, the functionality can not be verified in the test environment because MockCheckpointManger doesn't emit this event.

Please add this event to ICheckpointManager and emit it inside MockCheckpointManager#setCheckpoint to make it more consistent with RootChain contract.

Typo in EIP721Base domain separator implementation

It looks like there's a typo in EIP712Base implementation. It called getDomainSeperator but it should be getDomainSeparator
https://github.com/maticnetwork/pos-portal/blob/master/contracts/common/EIP712Base.sol#L46
It looks like this issue is repeated in variables and other functions.

I can open a PR but I'm not sure if it's ok since it would change the contract's interface.
DAI proxy's implementation contract depends on this getDomainSeperator function and it's deployed with the typo.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.