Sovereign Shards - MIP-7 - part - 2

6. Sovereign Shard Economics

As we look around on the blockchain space, we can see a set of approaches when it comes to dAppChain economics (Matic(Polygon) Supernets, Avalanche C-chain, Polkadot side chains, Cosmos Hub). The let’s say latest model is from Polygon, and it clearly resembles Polkadot and Avalanche, although it is slightly more customizable and it does not need validators to have too much stake.

In all of the 3 architectures (Polygon, Polkadot, Avalanche), validators stake in the main protocol pool and can choose what kind of sidechain they will validate. The validators get the rewards on the mainchain, in the forms of validator rewards from the main protocol emission. They can receive further incentives like transaction fees from the side chains. The main difference here is in the case of Polkadot, where validators do not choose, they will randomly validate every sidechain. Plus the number of validators in Polkadot is controlled by the mainchain and the entry price on the mainchain validators list is extremely high. Sidechain fees are received, but not extra incentives. Avalanche made it a little more customizable, as validators can choose to validate in certain sidechain. They still have a minimum limit for the validators, as they have to be in the mainchain as well. Rewards are given out as AVAX tokens, based on contributions on the mainchain. Plus transaction fees from the sidechain.

Polygon (Matic) is taking the most customizable approach from these 3 (in Cosmos, you can do whatever you want, but the ATOM tokens on the Cosmos Hub do not have any relevance). The idea is that the mainchain - let’s name it staking layer, manages the validators. On this staking layer, each sidechain have to deploy a contract in which it configures the rules (min/max validators, slashable offenses, additional validator criteria). Only validators with a stake on Polygon can register into these contracts. All validators receive POL rewards from the mainchain emission, they can receive additional rewards as txFees from sidechains and additional emission on sidechain, as other tokens. In the approach of Polygon, there is no minimum POL staked (so far). Validators do not need to work on mainchain - that is only keeping staking and validator management information, anyway. As POL is staked on the mainchain, validators receive rewards from there.

Taking all into consideration, the system will enable the most customizability, with less limitations, more freedom for builders, plus it reinforces the base token eGLD. The basic idea is the projects will have to deploy a config smart contract for the sovereign shard (more specifically this will be deployed through a factory SC, so projects do not need to change the code of the sovereign shard SC). In this they write the configuration of the sovereign and the rules. Validators have to come and stake through a new staking contract written in RUST (we need a new staking contract in order to be able to slash), this staking contract will delegate the received tokens to the system delegation module. Thus, this staking contract will earn eGLD rewards, and these rewards will be distributed according to each validator stakes inside this contract. These validators are not the same as the mainnet validators. A validator receives rewards only if he is a participant in at least one sidechain. This means validators on sovereignChain can utilize their eGLD funds, receive rewards in eGLD, and participate in sovereignChain processing for more rewards.

1. Sovereign Validators staking contract:

Starting from the liquid staking contract (GitHub - multiversx/mx-liquid-staking-sc) a new contract is built but without giving out the liquid staked positions. In the new staking contract all the delegation contracts from the mainnet which have open delegation spaces are registered, all which have under X% fee and which have at least Y% of APR. This list can be updated manually every day/week by using on-chain and oracle data. The sovereign validator sends eGLD into the sovereign validators staking contract. The contract will register its stake and make an asyncCall of delegate with all the given amount. This will delegate the amount to one of the prelisted delegation smart contracts.

unStaking/unBonding will follow the same way. The sovereign validators’ staking contract will forward the calls to the delegation contracts and resolve the requests.

claimRewardsFromDelegationContract - will call all delegation contracts where the sovereign validators staking contract has stake and claim rewards from there and deposit it as eGLD in the contract.

claimRewards - validators can call this endpoint and will receive rewards according to their stake in the contract. We can borrow the implementation from the legacy Delegation smart contract for this. Another approach/module which can be selected at deploy time by sovereign deployers is to compound rewards every day, and validators will be able to receive rewards only by unStake/unBond. In this case, we would use the liquid staking token formula and register the computed amount as share in the sovereign validators staking contract.

We add a limit on claimRewards - that only if the validator was actually part of at least one sovereign chain, he will receive the rewards. This is necessary because of the next small improvement: To whitelist this contract in the metachain, thus meaning that serviceFee for example for this contract will not be deducted on the delegation contracts, as this gives rewards for sovereignChain, which brings a lot of good to the main ecosystem, the staking provider on the mainchain has to allow skipping the serviceFee for the sovereign validator staking contract as well. Skipping services fees and making that customizable can come later as a proposal for the MultiversX protocol.

slash@validator@value - this endpoint can be called by the chain-factory-contract, will basically slash a certain amount of eGLD from the validators account.

distributeSlashed@list(address, value) - this endpoint can be called by the chain-factory-contract and will add to the validators balances the given amounts.

Sum of values < totalSlashed. Only existing validators can receive tokens from the slashed amounts.

2. Chain-factory-contract

This contract will keep the map of deployed sovereign shard config contracts. Plus it can interact with the sovereign validators staking contract, in order to slash validators. It will give random/deterministic chain IDs for each of the sovereign shards, and we can use these chain IDs to easily identify ESDT tokens as well (we may use these chain IDs in the ESDT token IDs).

It may whitelist/blacklist validators or sovereign chains.

deploySovereignChainConfigContract: Through this contract, a sovereign chain can be deployed. Deploying a sovereign chain will cost 1eGLD (we have 0.5eGLD for the cost of ESDT tokens). The user will send in the txData all the custom parameters through which he wants to deploy the config contract. The chain-factory-contract will call deployFromSource@parameters and set the user as the administrator on top of the chainConfigContract.

slash@validator@value: this endpoint can be called by chainConfigContracts only, which were deployed through the factory contract. This will further call the slash function on the sovereign validators staking contract.

distrubteSlashed@list(address, value): the same as slash endpoint.

3. Chain-config-contract

This contract will contain the configuration of the validators, the rules and this contract will deploy the sovereign bridge SC (we do not need to talk about that in this document).

This contract contains the rules for:

  1. Minimum/maximum validator number.

  2. Slashable offences

  3. Extra validator criteria:

    1. Minimum eGLD stake required (can be as low as 0.000000001).
    2. Additional stake in other tokens
    3. Was previously slashed
  4. Fee management:

    1. If fee’s are in EGLD, validators must deposit eGLD in this contract for genesis, as txs will need eGLD for payment.
    2. If any other token, genesis has to contain that token for at least a set of validators, as you need to bootstrap the network.
  5. Native token definition

  6. Additional rewards in other tokens

  7. Block time, size, epoch time.

  8. Whitelist of who can create tokens on sovereign. Whitelist of who can call registerNewESDTToken on sovereign bridge. If not set, anyone can create.

  9. Genesis time, genesis setup.

Register endpoint will be called by validators, the chain-config-contract will ask information about the validator from the sovereign validator staking contract and verify all the criterias and accept the validator after.

In case of extra rewards which are given out on the mainchain, deposits have to be made of those tokens, and setup of startTime, endTime, rewardsPerBlock (same as we do in farms on DeFi).

Genesis information will be extracted into a genesis.json file, through which the sovereign chain will start.

slash@validator@value@offence - this endpoint can be called by any validator from this sovereign chain, but it needs to have 67% of the signatures of all validators registered in this sovereign config contract.

Important aspect of this design:

Projects will easily launch any sovereign chain, new validators can join the chains easily (without the need of minimum 1250eGLD and validating on mainnet). Validators on sovereign will still earn eGLD, as they stake eGLD on mainnet, and we will have even more eGLD staked. The sovereign validator SC might be called from a liquid staking derivative contract as well, which gives out those positions in a liquid form. Fees on sovereign can be set as eGLD or other tokens. Other rewards can be given to sovereign chain validators, customizable by each chain.

Changing validator set on sovereignMultiSigContract:

In genesis, the sovereign shard starts with a defined set of BLS keys, these are written into the sovereignMultiSigContract as well. When there are changes of validator keys on the sovereign shard (at end of epoch) the current group of validators will create and sign an OutGoingTXData changeValidatorSet@LIST@LIST@BLSMultiSig

The contract verifies the BLSMultiSig first, then makes the validator set change. These changes will go through after epoch changes, the contract verifies according to the chainConfigSC whether the epoch has passed or not.

7. Multi VM for Sovereign Shards

The MultiversX protocol was designed in such a way that integrating a new executor, a new processor, even a new VM to be easy. Basically, the new VM has to satisfy the “VMExecutionHandler” interface. Even right now, the system has 2 VMs running on MultiversX - WasmVM which handles general smart contracts running on WASM, systemVM - specialized, defined system smart contracts written in GO.

In case of the sovereign shards, it is possible for one SC from WasmVM to call another SC from the systemVM through the “BlockchainHookInterface - using the ExecuteOnDestOnOtherVM endpoint. This is needed as in sovereign shards, both VM reside in the same shard. In the case of mainnet, WASM VM SCs can interact with systemVM only through asyncCall, as SystemVM is only in the metachain. Any new VM implementation can follow the guidelines to be compatible with the system, without the need to add custom code in the existing mx-chain-go codebase. Furthermore, components like StorageContext, BlockChainContext, MeteringContext and OutputContext resolve all the interfacing a VM needs with the blockchain data, also resolving gas consumption and creating VMOutput.

All VM processing start by calling RunSmartContractCall(vmInput *ContractCallInput), which needs to return a vmOutput structure. The system writes the data into the state trie only the information which is in the vmOutput structure.

When we consider any new VM on MultiversX, we have to consider that developers will want to interact with SCs from WasmVM as well, or saying it better, one SC should interact the same way with a wasmVM SC and with another VM SC. All the abstraction has to happen at the VM level. This abstraction on the WasmVM is fully done, as the VM is intelligent enough to know when to call the ExecuteOnDestOnOtherVM endpoint.

Technical details of how to implement EVM as a VMExecutionHandler

A few mentions here: as sovereign shards are highly scalable, use the best and most efficient consensus mechanism, transaction fees will be cheap. We know all the issues ERC standards have (allow infinity and reentrancy especially), it is the responsibility of developers to build UX and contracts in such a way that it will protect users. Thus, no infinity approval, only approve for the next transaction should be the way to go.

VMExecutionHandlerInterface:

// RunSmartContractCreate computes how a smart contract creation should be performed
RunSmartContractCreate(input *ContractCreateInput) (*VMOutput, error)

// RunSmartContractCall computes the result of a smart contract call and how the system must change after the execution
RunSmartContractCall(input *ContractCallInput) (*VMOutput, error)

The input information is prepared by the SCProcessor from mx-chain-go. This one we do not want to change, all abstraction has to be done at the EVM level.

From input *ContractCreateInput the EVMInputCreator component creates the EVMInput and run the actual EVM SC. The EVM SC exists as a go standalone components:

Take EVM, add an abstraction layer between MvX interfaces and EVM interfaces. In order for the EVM to communicate with the information (especially blockchain, state, transaction data) has to use the BlockChainHookInterface. More specifically, the EVM opcode of readStorageFromTrie(key) has to call the storageContext.ReadFromStorage(scAddress, key).

The storageContext from the VM can handle storage changes from the current transaction execution, and will optimally handle the read from storage from local cache, if that storage key was already read/modified in the current execution context. Write to storage EVM opcode has to call SetStorageToAddress(address, key) from the storageContext component.

The final step is to write into the blockchain the state changes the EVM. The EVM should use the outputContext component, as that one together with the storageContext keeps the list of modified accounts, modified storages and has the capability of creating the vmOutput. The scProcessor from mx-chain-go will take the vmOutput, will verify its validity and only if all executions were of success will write the final state changes into the actual blockchain (to the trie).

One more topic is metering. EVM metering is directly inside the VM. The VMExecutionHandler has a function of GasScheduleChange(newGasSchedule map[string]map[string]uint64) - which receives the cost of every opCode as a map. The EVM needs the wrapped set functions which actually writes this information into the OPCODES structure of the EVM.

EVM address is 20byte and MvX address is 32 bytes long. The proposal is to not change the system at MultiversX level, but to have internal transformers in the EVM. Thus all the contract calls in the EVM internally will work with the last 20bytes of an MvX address. When a contract is running on EVM it can read from its own address, so at runtime we know the full address of the contract and when read storage/write storage is called, we just prefix it with the 10bytes of ZEROs and the VMType (2 bytes) - the standard SC address creation process on MvX.

When an EVM SC is calling another EVM SC, the call is with 20bytes, so we prefix it with the deterministic values (explained above), get the code from the accounts trie and run it. Tokens on EVM are saved in the contracts storage, the contract (like ERC20) will use the last 20bytes of any MvX address to save the information about that user. When EVM OPCODE of GetCaller is used, the implementation will return the last 20bytes of the ContractCallInput.Sender value.

If one contract from MvX is called with only 20bytes per address, the execution will be stopped as the arguments size is wrong. So when we call WASM VM contracts from EVM, we must do it with the full address. For contracts this is easy and EVM cannot call anything else than another contract. Even with this, we can make claiming tokens from EVM to ESDT work with ERC Wrapper contracts.

EVM and WASM VM interacting

As explained above, the WASM VM integrated the new BlockchainHook public function of ExecuteOnDestOnOtherVM. If a new VM is fully integrated, it can be added into the vmContainer component with a new baseAddress. (05 for WASM VM, 256 for SystemVM). From the SCAddress, we take out the base address (byte number 10 and 11 from the address) the scProcessor, the blockchainHook can compute which VM has to be called. EVM will receive upon adding to the vmContainer a new base address - this means CreateContract OpCode from EVM has to take this into account when creating the address upon deployment of a new contract.

EVM Opcode of Call will call an internal function of the new EVM implementation, this uses the computation to see whether the execution has to be done in EVM or on other VM. If it is another VM then it will call the blockchainHook.ExecuteOnDestOnOtherVM. This function will return a VMOutput. The VMOutput can be merged into the current outputContext and storageContext, pushing the PushContext public functions.

ESDT to/from ERC20. ESDTNFT to/from ERC721

At start there is a big paradigm difference, like on ESDT uses the transferAndExecute paradigm (the sender has to transfer the tokens and call the execution of a SC), in ERC developers use transferFrom paradigm mostly:

  1. The user first approves SC X to take tokens out of the users “wallet”, in terms of SC, in the ERC20 contract it is registered that userX allowed SC X to move Y amount of tokens from the user.
  2. On the SC Execution (next set of user operations/transactions) the transferFrom endpoint from the ERC20 contract is used to move funds from the user to another account, to the SC. This is something we strictly prohibit in terms of ESDT. As this opens up a lot of attack vectors and leads to draining of funds on EVM compatible chains for ERC20 tokens. A malicious dApp can make a user sign a transaction, in which the user will explicitly allow the malicious SC to take the funds from the users.

In order to make the 2 standards interoperable a new wrapper/safeESDT contract is created in which the user deposits the ESDT and this allows the transferFrom functionalities. The user at deposit time, could define the list of scAddresses which are allowed to take the funds from this safeESDTContract. The user could claim these tokens back from the contract.

The EVM VM would call safeESTContract.transferFrom(user, scAddress). Similar wrapperESDT contract standards can be made for ERC1155, ERC20, ERC721 or other ERC token standards.

When a user wants to claim as ESDT token a token which balance is save in an ERC20 contract, the following process will happen:

  1. Users call the ERC20 contract on EVM, which will burn the ERC20 tokens and do callContract(ERCWrapper) on the WASM VM.
  2. WASM VM will register the received token under the 20bytes address (as EVM knows about 20bytes only)
  3. User claims from WASM VM wrapper contract its own tokens, the contract checks that last 20bytes == callInput.CallerAddress[12:32]
  4. The action can happen in the same transaction as the wrapper contract on WASM VM has access to ContractCall.OriginalCaller, so if the received argument from the ERC20 EVM contract is equal with last 20 bytes of OriginalCaller, the wrapper contract can mint and send the ESDT token to the OriginalCaller.

Conclusions

With Sovereign Shards we want to give an SDK for all builders to run their own highly efficient chains, but which is seamlessly connected and integrated into the global markets of MultiversX. Give developers freedom, give users the power to enjoy all dApps seamlessly, make it feel like they are on a single blockchain. One wallet to interact with all. Composability and interoperability built into the design and architecture of the system. New paradigms to leverage existing infrastructure and enhance the user experience. Usability of all chains simplified by systems like relayed transactions and paymaster smart contracts.

Through using a sovereign shards builders can leverage all the technology and work put behind the wallet, explorer, xPortal, microservices and so forth. All this with built-in bridges, with tightly coupled integration with mainchain smart contracts, attestation for executing transactions in both chains and with eliminating the need for trust on an external set of actors - like bridge relayers. Sovereign Validators by construct will process and execute cross chain transactions, all execution over the bridge are executed in the name of the user, thus enhancing the composability, interoperability and seamless user interactions across the MultiversX ecosystem/shards and the sovereign shards.

11 Likes