A Guide on XYO's Simple Consensus Smart Contract Library (ZOS Upgradeable)

Hi all! Here is a first draft of the guide. I will most likely update this a few times this week since I'll be adding a contract. I would also look at the commands even more than the addresses, since there may be some newer contracts in deployment. I hope this helps anyone with deploying upgradeable contracts on the mainnet.

SIMPLE CONSENSUS SMART CONTRACT (SCSC) LIBRARY - A guide into how we upgrade and our contract logic

Short Description

A Simple Consensus Smart Contract library for all nodes in XYO

Long Description

This package has been built to streamline the dApp build process for anyone ready to integrate XYO into their project.
Especially crucial in this library are the XyGovernance and XyStakingConsensus contracts.



  • In the command line go ahead and install using npm
    npx zos link dapp-scsc-solidity


  • Familiarity with
    • Solidity
    • Web3
    • Truffle
    • Ganache


  • Watch this video on staking a node in XYO
  • Check out dApper
    • dApper allows you to interact with the smart contracts from the scsc library on the browser

How We Integrated Upgradeability

Below are the commands that we used to deploy the library to Kovan and Mainnet

Special thanks to these blog posts on deploying EVM Packages from ZeppelinOS

Deployer for kovan: 0x316D5E10f4E4ad94499149c0131a44FC17EF995B

Kovan Deploy

npx zos session --network kovan --from 0x316D5E10f4E4ad94499149c0131a44FC17EF995B --expires 5000

// Initialize the contracts for session

npx zos push
npx zos create XyBlockProducer --init initialize

We take note of the address of the contract - 0xb9452ee24cf08eaedf64F3B81f8727f5bd0Ea084

npx zos create PLCRVoting --init initialize --args "0x9071a6fc3c23eb6f4a8f7a2bc2309a7b368f272f"

We take note of the address of the contract - 0x210241f42bC94Eb9da7b4E0A841f3b340B569291

npx zos create XyGovernance --init initialize --args "0x9071a6fc3c23eb6f4a8f7a2bc2309a7b368f272f,0x210241f42bC94Eb9da7b4E0A841f3b340B569291,[400000000000000000000000,172800,172800,172800,50,50,50,66,1000000000000000,1,11520,11520,0,20]"

We take note of the address of the contract - 0xbF68070E5E84cae28f10161088edA1747A5963Ee

npx zos create XyStakingConsensus --init initialize --args "0x9071a6fc3c23eb6f4a8f7a2bc2309a7b368f272f,0xb9452ee24cf08eaedf64F3B81f8727f5bd0Ea084,0xbF68070E5E84cae28f10161088edA1747A5963Ee"

We take note of the address of the contract - 0x1a2C4a6Ffd72848E7bD63d2177c29a0aC80c6386


QmNPKPDj8UjNyy3ewLpyCUAcrAPEZoRtpAFwWtrZP3uEXX XyBlockProducer.json
QmZrbFNd21fY1Q6tJb1hLthaUyfHTEvVc5eJJdSdHQSTXi XyFaucet.json
QmcQhGekFrFGDPSy8epReXyBiYqLLgNd9rCcjMz341pF8L XyGovernance.json
QmTbUrie2GyVm6yJjQ3RHxinQtaqmLdtor1FpsYJD5kiA3 XyStakingConsensus.json
QmTGsMMiy2doKXWyEYci11btTpSQFnFJEowbFhzuVnjTcy kovanABI


0x1a2C4a6Ffd72848E7bD63d2177c29a0aC80c6386 XyStakingConsensus
0xb9452ee24cf08eaedf64F3B81f8727f5bd0Ea084 XyBlockProducer.json
0xbF68070E5E84cae28f10161088edA1747A5963Ee XyGovernance.json
0x9071a6fc3c23eb6f4a8f7a2bc2309a7b368f272f XyFaucet.json

Minimized Kovan:

QmPSNLi99b91AR93AhS7P8TzgETp299R4KurSaFzqn2Dsa XyBlockProducer.json
QmZrbFNd21fY1Q6tJb1hLthaUyfHTEvVc5eJJdSdHQSTXi XyFaucet.json
QmYJhLPmq5GNTQDkWonHV4693YdoEJ1Bt9yz5yz15r6s2Z XyGovernance.json
Qmf6MHXSe4mKYTXbB5nEyUdKagpFo8ZWMSU96rNWqx293D XyStakingConsensus.json
QmYBBNitDFPJVkQkXpZbS16rqJhRU2Eg2teCzaT6jGGY7o minimizedABI

Mainnet Deploy

We change the ZOS Session for mainnet deployment

npx zos session --network mainnet --from 0x6792B02f88b32C4FE8e31cfA41ae5aF44865f930 --expires 5000

Add the contracts to the session

npx zos push

Start initializing the contracts

npx zos create XyBlockProducer --init initialize


npx zos create PLCRVoting --init initialize --args "0x55296f69f40Ea6d20E478533C15A6B08B654E758"


npx zos create XyGovernance --init initialize --args "0x55296f69f40Ea6d20E478533C15A6B08B654E758,0x72bCDb36d1545FEA06905a1bb4998424580AAee6,[400000000000000000000000,172800,172800,172800,50,50,50,66,1000000000000000,1,11520,11520,0,20]"


npx zos create XyStakingConsensus --init initialize --args "0x55296f69f40Ea6d20E478533C15A6B08B654E758,0xd3034c290E19959Fdc18E5597F375CA51BFB0c41,0x01925d0fFE4a6a6162B51ba611e3D4780Fc2dF42"


We minimized the ABI so that we could reduce gas fees and improve performance

Mainnet Minimized ABI:

QmWCMjwu78qSDPzdrHrBL4BzFLLWTgnRgV5HCbf5aQpmhC PLCRVoting.json
Qmc2kRGQQ5GumtFEvZ4EEdZU2nos45bERCbrwxKKYtokxY XYO.json
QmbZBv5LT1CxBG79inzcerG5DEtNwAYyLNUFQaULi5kYiH XyBlockProducer.json
QmcszeMWmdq2ZNLq6vsMtsFvcgVdTCjRSgcXaVgq37aphu XyGovernance.json
QmWkzxNb5yK82y9bDbkr8ucjKYe2QRdpDrP5DN3gTU3gKP XyStakingConsensus.json
QmfXE9DyRAf43fwtYig2RstHbJxxYJjvjAuGqwmEMZmCdj minimized
0x0242514106114DEaA99Fd81574142c36Edb03B6D XyStakingConsensus
0xd3034c290E19959Fdc18E5597F375CA51BFB0c41 XyBlockProducer.json
0x01925d0fFE4a6a6162B51ba611e3D4780Fc2dF42 XyGovernance.json
0x72bCDb36d1545FEA06905a1bb4998424580AAee6 PLCRVoting.json
0x55296f69f40Ea6d20E478533C15A6B08B654E758 XYO

Please note that we followed the steps outlined in the 3 part series, the main changes we had to make were in the arguments per our contract needs.

We were able to successfully deploy these contracts on both Kovan and the mainnet.


Awesome! Mind pasting the guide instead of linking it?

This way we don’t need to open a new tab or even can quote/ask things directly in here :slight_smile:

@martriay I can do that no problem.

1 Like

I also wanted to share with the community how we stake on our network through the SCSC. I also made a few videos on the concept of staking in our network and the UI from our Matrix app.

How to Add Stake to Diviner

Adding stake to a diviner on our network is a vital step in utilizing our network, and further understanding it.

Access our SCSC library through IPFS

use this hash QmaHuJh3u5J4W8WYhJnfH1yZUWWwUaehsVLbUPMEd4ymqN

Then direct your browser to use our dAppper tool

with the hash


The contract will load, giving you access to the contracts through the contract simulator.

Start with the XyERC20Token

Connect your metamask wallet on the Kovan network

Check your balance using the balanceOf() function from the ERC20 contract

Once you have verified that you have enough balance to stake the diviner, select the XyStakingConsensus contract This contract stores all the stake of the network

Approve the stake for the Diviner in the XyERC20 contract (make sure that you have the address for the XyStakingConsensus) using the approve() function.

Go through metamask to submit the transaction. You have now approved stake, let’s keep going.

Create a diviner

The diviner is represented by a Stakable token

  • Mint one token with your wallet address by selecting the XyBlockProducer and the address below

  • Select the mint() function and paste your wallet address into the beneficiary field

  • Confirm the transaction on metamask

This will produce one non-fungible token (ERC721). This is unique to this specific diviner.

Then select the tokenByIndex() function and enter 0 for your token address.

Copy the token address, this is virtual id of your diviner

Return to the XyStakingConsensusContract and select its address below

  • Select the stake() function
  • Paste the diviner id into the stakee field
  • enter an amount to stake (make sure it is in your approved limits!)
  • Click execute

You have just successfully added stake to a diviner!

note you are the staker, and the stakingId is the ledger of the stake that you have in the diviner

To check out the data of the stake, select the stakeData() function, paste in the stakingId in the sole field.

You will now get a returned JSON object with your stake amount, the block it was staked on, the staker, and the stakee.





  • Sends a specific value of tokens from your XYO account to another

  • parameters

    • address _to
    • uint256 _value


  • Sends a specific value of tokens from one (not yours) XYO address to another XYO address

  • parameters

    • address _from
    • address _to
    • uint256 _value
  • returns

    • bool success


  • Sets an allowance for tokens for another address check out our staking walkthrough for an example

  • parameters

    • address _spender
    • uint256 _value
  • returns

    • bool success


  • Sets an allowance for tokens for another address with a notification for the other contract

  • parameters

    • address _spender
    • uint _value
    • bytes memory _extraData
  • returns

    • bool success & approval notification with _value and _extraData


  • destroys tokens

  • parameters

    • uint256 _value
  • returns

    • bool success


  • Destroys tokens from another account

  • parameters

    • address _from
    • uint256 _value
  • returns

    • bool success


This contract is used to track ownership of stakable addresses in XYO
This contract is upgradeable


  • Allows a contract governor to add and remove a block producer

  • parameters

    • uint stakee
    • bool enable


  • Mints a stakable address with the account has as the token id
    this emits a transfer event to the sender

  • parameters

    • address beneficiary


  • Burns a token (only a governor can do this)

  • If the token belongs to a block producer, it deletes the token from its listing

  • parameters

    • uint stakee


  • A method to view if a stakee exists

  • parameters

    • uint stakee
  • returns

    • stakee


  • A method to view if a stakee is a block producer

  • parameters

    • uint stakee
  • returns

    • stakee from the blockProducersIndex


  • A method to view the number of block producers

  • returns

    • number of block producers


Manages the stake for multiple clients in a decentralized consensus
This contract is upgradeable


  • Returns the latest block submitted on the chain

  • returns

    • uint _latest


  • Withdraw reward balance

  • parameters

    • uint xyoBounty
  • returns

    • uint requestId


  • Escrows eth and XYO to ensure that it covers the answer mining cost

  • Stores the new request in the request pool and emits the submission

  • parameters

    • uint request
    • uint xyoBounty
    • address xyoSender
    • IXyRequester.RequestType requestType


  • Submits a new block at the consensus blockchain, with a verified stake over 51% and returns weiMining for successful creation.

  • parameters

    • uint blockProducer
    • uint previousBlock
    • uint[] memory _requests
    • bytes32 payloadData
    • bytes memory responses
    • address[] memory signers
    • bytes32[] memory sigR
    • bytes32[] memory sigS
    • uint8[] memory sigV
  • returns

    • uint (newBlock)


  • A method to view the number of requests in the consensus block

  • returns

    • requestChain.length


  • A method to view the number of blocks in the consensus chain

  • returns

    • blockChain.length


  • A Payment on delivery contract, check out our Payable On Delivery Demo to see how it works
  • This contract is upgradeable


  • Called by the client to request an intersection question (is the item delivered?)

  • parameters

    • uint requestId
    • uint xyoBounty
    • uint xyoPayOnDelivery
    • uint weiPayOnDelivery
    • address payable beneficiary


  • Called by SCSC, if there is an intersection, executes a transfer to beneficiary and deletes the request from the request pool

  • parameters

    • uint requestId
    • IXyRequester.RequestType
    • bytes memory responseData


  • This contract is called in submitResponse with the request Id and who needs to be paid. In the submitResponse contract that is the beneficiary. This contract is a refunding mechanism that is utilized as a payment mechanism upon successful completion of a request/response.

  • parameters

    • uint requestId
    • address payable payee


  • Gets the number of requests currently in play

  • returns

    • requests.length

I suggest you update the original post with the guide so it’s the first thing you see :slight_smile: