@moneyonchain/shared

1.5.1-beta.2 • Public • Published

MOC Shared

The moc "Oracles and Beyond" project is composed by four subprojects that are in different git repositories:

  1. OMoC-SC-Shared: This repo
  2. MoC-Gobernanza: Voting Machine
  3. MoC-Vesting: Vesting Factory and Vesting Machines
  4. OMoC-Decentralized-Oracle: Delay, Staking & Oracle Machine
  5. incentives_v2: Incentive contract

This repository contains common library code used by the rest of the projects and the main deploy script that deploys the smart-contracts of all the projects into the blockchain. To use the library some knowledge of nodejs, npm, truffle migrations, blockchain and rsk network nodes management is needed.

Please refer to Changelog for version notes and requirements.

Smart contract deployment

MOC-Flow Configuration

The MOC Flow components configuration parameters can be loaded from a local .env file or from the system environment. The following values are defined.

Rewards Coiner configuration

  • ORACLES_REWARD_COINER_TOTAL_MINT_TARGET: Total amount of tokens to mint in weis (e.g: '7650000000000000000000000')
  • ORACLES_REWARD_COINER_FIRST_STAGE_PCT: % to mint of remaining tokens in the Stage 1 minting step (e.g: '3')
  • ORACLES_REWARD_COINER_SECOND_STAGE_CONSTANT: constant amount to mint in the Stage 2 minting step until total mint target is reached (e.g: '100000000000000000000000')
  • ORACLES_REWARD_COINER_SECOND_STAGE_BEGIN_THRESHOLD: threshold in amount of minted tokens to end fractional stage 1 and commence constant emission (stage 2) (e.g: '300000000000000000000000')
  • ORACLES_REWARD_COINER_MINT_BLOCK_INTERVAL: minimal interval in # of blocks to call a minting step (e.g: '6600').

Dripper configuration

Buffer configuration

  • <buffer>_THRESHOLD:
  • <buffer>_SPLITS: Ratio of split between outputs. (e.g: [80, 10, 10])
  • <buffer>_OUTPUTS: Which contracts the buffer will emit tokens to. (e.g: '@moc/oracles/Supporters')
  • <buffer>_THRESHOLDS: Exit thresholds to trigger each buffer output.

In the above entries, replace buffer with the appropiate prefix matching the buffer contract you want to configure:

  • BPRO_REWARDS_BUFFER
  • MOC_REWARDS_BUFFER
  • RIFPRO_REWARD_BUFFER
  • BITPRO_REWARD_BUFFER
  • BTC_FEES_BUFFER
  • RIF_FEES_BUFFER

e.g: to configure splits for the Rifpro Rewards buffer you should use the configuration entry RIFPRO_REWARD_BUFFER_SPLITS; to configure outputs for the Oracles Reward Buffer #1 use ORACLE_REWARD_BUFFER_1_SPLITS, respectively.

Reverse Auction configuration

  • <revauct>_DEX: The DEX contract address to call for conversion.
  • <revauct>_TOKEN_IN: The input token to be converted. When RBTC const (address(bytes20("RBTC"))), the Reverse Auction's can receive a transfer of RBTC and WRBTC. The sum of those balances will be used to insert a market order. When it's any other token address, it can only receive those tokens and only that balance will be used to insert a market order.
  • <revauct>_TOKEN_OUT The output token to be transferred to the output account. When RBTC const (address(bytes20("RBTC"))), the output account will receive the RBTC and WRBTC balances of the Rev Auc all in RBTC. When it's any other token address, it will receive that token's balance of the Rev Auc.
  • <revauct>_OUTPUT_ACCOUNT The output account to deposit the converted tokens.
  • <revauct>_ORDER_LIFESPAN Order validity span in DEX ticks, e.g: 1 . Use zero (0) to ask the DEX for a default value.
  • <revauct>_MULTIPLY_FACTOR 1
  • <revauct>_ORDER_THRESHOLD 20000000000000000000
  • <revauct>_EXIT_THRESHOLD 40000000000000000000
  • <revauct>_USE_BUY_ORDER e.g 1 Issue "SELL" orders if zero, BUY orders otherwise.

The available <revauct> prefixes for the respective components are:

  • REVAUCT_MOC2RIF
  • REVAUCT_RIF2MOC
  • REVAUCT_MOC2BTC
  • REVAUCT_BTC2MOC

Running a Local Environment

  • Download and install node 10.x
  • Download and install ganache-cli with npm (globally): npm install -g ganache-cli
  • Run ganache-cli using the script: scripts/run_ganache.sh
  • Clone the moc-shared repo: git clone git@github.com:money-on-chain/OMoC-SC-Shared.git moc-shared
  • Switch to the moc-shared directory and run npm install to install dependencies
  • Deploy the contracts: npm run deploy
  • Once the tasks have finished you'll have at Ganache a running version of the contracts. The addresses of the contracts and the corresponding openzepplin proxies can be seen by running: less ./.openzeppelin/dev-12341234.json to check the file contents. Usually the registry proxy address is need by the Oracle Server or the UI, you can fetch the address you need using jq: cat ./.openzeppelin/dev-12341234.json | jq -r '.proxies["@moc/shared/Registry"] | .[] | .address'.
  • The abis and binaries are stores in the usual truffle directory: build/contracts/*.json

Local Environment parts

This setups up the basics of what you'll need. To have the full project running locally you'll also need to follow:

Rsk testnet deployment

The deployment process for the rsk testnet network is similar to the local environment deploy but without running the ganache block chain server.

  • Download and install node 10.x
  • Clone the moc-shared repo: git clone git@github.com:money-on-chain/OMoC-SC-Shared.git moc-shared
  • Switch to the moc-shared directory and run npm install to install dependencies.
  • Some address must have RBTCs to pay for the deployment gas cost, the private key of this address must be saved to a file called .env in the project root directory. Edit the .env file and set the key there:PRIVATE_KEY=9999999999999999999999999999999999999999999999999999999999999999 Replace 9999...9999 with the real private key.
  • Deploy the contracts: npm run deploy -- --network network_name. The network name corresponds to the configuration of truffle in the truffle-config.js file, some possible values are rsk_nodes, rsk_testnet (See bellow).
  • Usually the rsk public nodes has limits on the amount of requests/min and are not suitable for a full deploy. To run the deploy process a private node that has no restrictions must be used.
  • Once the task has finished you'll have the contracts deployed in the corresponding network. The addresses of the contracts and the corresponding openzepplin proxies can be seen by running: less ./.openzeppelin/dev-31.json to check the file contents. Usually the registry proxy address is need by the Oracle Server or the UI.

Library Usage

The library is distributes as a tgz npm package file. To install the library run: npm install --save http://omoc-do.coinfabrik.com/npm/moc-shared-0.1.0.tgz

After installation the javascript helpers can be included using: const helpers = require('@moc/shared/lib/helpers'); The truffle migration scripts can also be reuse by including them in any other migration script: const step = require('@moc/shared/migrations/2_init_openzepelin')

The npm package include:

  • The contracts public interfaces in .sol source code format.
  • The compiled contract public interfaces binaries and abis: build/contract/*.json
  • The governor binaries and source code.
  • A generic truffle configuration that can be reused in other projects (lib/truffleConfig.js).
  • Javascript tools to deploy and access openzeppelin proxy contracts.
  • Javascript tools to run truffle migration steps from other projects (including moc-shared itself).
  • Javascript tools to parse truffle command arguments to detect network type and development/production environment.

Contracts

  • contracts: This folder is the root directory for all contracts

    • Main Interfaces:

      • IStakingMachine.sol
      • IVotingMachine.sol
      • IVestingFactory.sol
      • IVestingMachine.sol
      • IRegistry.sol: The registry contains all system parameters.
    • MOC Oracles Interfaces:

      • IDelayMachine.sol
      • IOracleManager.sol
      • ICoinPairPrice.sol
      • ISupporters.sol
      • IOracleInfoGetter.sol
      • IMintableERC20.sol: This interface represents an ERC20 token that can mint tokens.
      • IPriceProvider.sol
      • IPriceProviderRegisterEntry.sol: Represent a price provider that has a type (calculated, published) that can be queries.
    • Contracts:

      • GovernedRegistry.sol: This is a governable eternal storage (a key/value store) contract used to store system parameters.
      • RegistryConstants.sol: This contract declares the keys used to access the registry.
      • IterableWhitelistLib.sol: A library used filter contract access (TODO: in the future this must be moved to the lib directory)
      • Migrations.sol: This is a truffle standard migration contract. We have a copy here, so the rest of the project can reuse it.
  • contracts/lib: This folder contains libraries that are reused by the rest of the projects.

    • AddressSetLib.sol: An enumerable set of addresses.
  • contracts/change: This folder contains change contract that are applied by governance during deployment.

    • MocRegistryInitChange.sol: Set the initial parameters of the system in the registry via governance.
    • TestMOCMintChange.sol: Mint tokens via governance.
  • contracts/moc-governance: This is part of MOC governor.

    • IOZAdminUpgradeabilityProxy.sol: An interface compatible with openzeppelin admin upgradeability proxy.
    • IOZProxyAdmin.sol: An interface compatible with openzeppelin proxy admin contract.
  • contracts/moc-governance/ChangersTemplates:

    • UpgraderTemplate.sol: An example of a change contract.
  • contracts/moc-governance/Governance: This is part of MOC governor.

    • ChangeContract.sol: Interface that all change contracts must implement.
    • Governed.sol: Interface that all governed contracts must implement.
    • Governor.sol: The governor contract.
    • IGovernor.sol
    • Ownable.sol: Openzeppelin ownable contracts.
    • ReentrancyGuard.sol: Openzeppelin reentrancy guard contracts.
  • contracts/moc-governance/Upgradeability:

    • UpgradeDelegator.sol: This is part of MOC governor system and adapts the govenor to the openzeppelin proxy admin.
  • contracts/testing_mocks: This contract are used for testing proposes only (don't deploy them to mainnet).

    • AddressSetLibMock.sol
    • GovernedERC20.sol
    • MockGovernor.sol

Javascript tools and libraries

The lib directory include some reusable javascript libraries:

  • The helpers.js file contains the helpers used to deploy and access openzeppelin proxies.
  • The rest of the files in the lib directory correspond to the truffle configuration described bellow.

Truffle configuration

Truffle configuration file truffle-config.js is executed by truffle and as result must export an object with the configuration parameters. We use a common configuration for all project based on the file lib/truffleConfig.js. Each project instead of declaring its own config does the following:

const truffleConfig = require('@moc/shared/lib/truffleConfig');

// This gets the global configuration, change parameters here if needed.
module.exports = truffleConfig.getConfig();

This way the configuration in the moc-shared project is reuse everywhere. Also we add some values to the configuration object that are used by our own deploy scripts (and ignored by truffle). The configuration is build by the following files that are in the lib directory:

  • truffleConfig.js: The main script that must be included in truffle-config.js
  • coinPairConfig.js: Contains the list of coin pairs that must be deployed in mainnet.
  • registryConstants.js: This script generate the RegistryConstant.sol file and, also have the corresponding key declarations for the migrations scripts.
  • registryInitChangeContractGenerator: This script generates the MocRegistryInitChange.sol script setting the initial values that are stored inside the registry.

Helper scripts

In the scripts directory there are a few helper scripts that can be used to interact with the system. There are three kinds of scripts:

  1. Truffle scripts that are written in nodejs (.js extension) and must be executed with truffle. See writing-external-scripts. Truffle takes the network name as parameter so this kind of scripts can be used on a development network (ganache based), on a testnet or mainnet network (rsk/ethereum).
  2. Shell scripts that are used to interact via curl with a local ganache instance. This kind of scripts cannot be used in a testnet or production, they use ganache specific rpc calls.
  3. Python scripts used to interact with ganache, they are a more complicated version of the shell scripts.

Truffle scripts

The truffle scripts make calls to the smart contracts. The address of the different contracts are taken from the openzeppelin configuration file, this file is created during deployment: ./openzeppelin/dev-NETID.json, where NETID is the network id (31 for rsk, 12341234 for ganache, etc).

Some address must have RBTCs to pay for the deployment gas cost, the private key of this address must be saved to a file called .env in the project root directory. Edit the .env file and set the key there:PRIVATE_KEY=9999999999999999999999999999999999999999999999999999999999999999 Replace 9999...9999 with the real private key.

  • scripts/createMachines.js After the initial deploy a set of vesting machine must be created. To create the vesting machine a json file with the information of the holders, timestamps and corresponding percentages must be created. The payments_example.json contains an example of that file.

    • Create a payment description file payments_description_file.json based on payments_example.json
    • Run npx truffle exec --network some_network_name scripts/createMachines.js <payments_description_file> The network parameter can be omitted to use the local ganache installation or can be any network described in the truffle-config file.
  • scripts/changeMinToken.js To mint tokens by governance run:

    • npx truffle exec --network some_network_name scripts/changeMinToken.js <destination-address> <token-amount> The network parameter can be omitted to use the local ganache installation or can be any network described in the truffle-config file.
  • scripts/setTGE.js Set the Token Generation Event in the Vesting Machine Factory. This script takes no parameters, the Vesting Machine Factory smart contract takes the current block chain timestamp as the TGE time.

    • npx truffle exec --network some_network_name scripts/setTGE.js
  • scripts/setVestingTotal.js Set the total of MOCs to distribute to a specific vesting machine. It takes the vesting machine address and the total as arguments.

    • npx truffle exec --network some_network_name scripts/setVestingTotal.js <vesting-machine-address> <total-mocs>
  • scripts/transferOwnership.js Transfer the ownership of some governor. This script is very RISKY !!!!

    After the transfer you will lose control over the governor!!!!

    • npx truffle exec --network some_network_name scripts/transferOwnership.js <governor-address> <new-owner-address>
  • scripts/transferOwnershipToVoting.js Same as transferOwnership.js but transfer ownership to the voting machine smart contract

    After the transfer you will lose control over the governor!!!!

    • npx truffle exec --network some_network_name scripts/transferOwnershipToVoting.js
  • scripts/changeImplementation.js Change the implementation of a smart contract using the current governor and the current bytecode. For example if executed with @moc/oracles/Staking it take the current proxy address of the staking contract and the governor from .openzeppelin/dev*.json and change the implementation using the binaries from the @moc/oracles npm project. This script can optionally take two arguments in which case the first argument is the name of the proxy in .openzeppelin/dev file and the second one can be:

    1. The name of the contract of the new implementation that will be deployed.
    2. The address of the new implementation.
    • npx truffle exec --network some_network_name scripts/changeImplementation.js <contractName>
  • scripts/executeChangeContract.js Executes a change contract using the current governor.

    • npx truffle exec --network some_network_name scripts/executeChangeContract.js <changeContractAddress>
  • scripts/runcChangeContract.js Deploys a change contract and then run it using the current governor. This script takes a variable list or arguments that are passed to the constructor of the change contract.

    • npx truffle exec --network some_network_name scripts/runChangeContract.js ...variable_args
  • scripts/getContractsAddresses.js List the contract addresses from .openzeppelin/dev*.json.

    • npx truffle exec --network some_network_name scripts/getContractsAddresses.js
  • scripts/changeOwner.js Change the owner of any Ownable contract.

    • npx truffle exec --network some_network_name scripts/changeOwner.js contractAddress newOwner
  • scripts/scriptHelpers.js This is not a script by itself but a library of helpers used by the rest of the scripts

Shell scripts

  • scripts/pack.sh: do the build and a copy the resulting .tgz a specific server via scp.

  • scripts/run_ganache.sh: Run the ganache-cli server with deterministic addresses and a specific network id, eth amount and time.

  • scripts/ganache_mine.sh: Mine the given amount of blocks

  • scripts/ganache_continue_mine.sh: Mine two blocks every 5 seconds

  • scripts/add1day.sh, scripts/add7day.sh, scripts/add1hour.sh: Advance the time of the blockchain by the given amount

  • scripts/evm_snapshot.sh: Take a snapshot of the ganache blockchain state

  • scripts/evm_revert.sh: Restore the state of the blockchain to the last snapshot

Python scripts

Development

Build

We use a npm packed tgz file to distribute the project.
To build the project the smart contract must be compiled and then everything must be packed and published using a web server.

  1. Compile the smart contracts on each project by running: npm run compile
  2. Pack the project: run npm pack that generates a packed .tgz npm package
  3. Copy the generated .tgz file to a web server to be published. The script: scripts/pack.sh do all those steps.

Selecting what goes into the packed file

It is important to note that each processed file is whitelisted using NodeJS files entry.

This means that new contracts must be included at:

	<Repos>/package.json
		"files": [
			"/lib",
			"/build/contracts/AddressSetLib.json",
			"/build/contracts/GovernedERC20.json",
			"/build/contracts/GovernedRegistry.json",
			"/build/contracts/Governor.json",
		...

Tooling

This repo uses solhint and eslint linters to check errors in solidity and js code respectively.

To format the code prettier and prettier-plugin-solidity are used.

To avoid clashes between eslint and prettier we use eslint-config-prettier to disable some eslint rules. For more details see: integrating-with-linters

Finally husky executes lint-staged during the pre-commit and lint-staged runs the linters and formatters over the code.

Readme

Keywords

none

Package Sidebar

Install

npm i @moneyonchain/shared

Weekly Downloads

0

Version

1.5.1-beta.2

License

none

Unpacked Size

6 MB

Total Files

154

Last publish

Collaborators

  • jbokser