Main Contract
  • Introduction
  • Money on Chain platform
    • Main concepts
    • System states
    • Public actions
      • User actions
      • Process actions
    • Contracts architecture
      • MoC
      • CommissionSplitter
      • MoCState
      • MoCBucketContainer
      • MoCSettlement
      • MoCHelperLib
      • MoCLibConnection
      • MoCConverter
      • MoCExchange
      • MoCConnector
      • MoCBProxManager
      • MoCInrate
      • MoCVendors
      • MoCWhitelist
      • MoCBase
      • OwnerBurnableToken
      • BProToken
      • DocToken
      • MoCToken
      • PriceProvider
    • Contract mocks
    • Relevant patterns and choices
    • Data dictionary
    • Getting started
  • Integration with MoC platform
    • Introduction to MoC
      • The MoC Contract
      • MoC Precisions
      • MoC State Contracts
    • Getting BPros
      • Minting BitPros
      • Redeeming BitPros
    • Getting DoCs
      • Minting DoCs
      • Redeeming DoCs
        • On Settlement: redeemDocRequest
        • On Settlement: alterRedeemRequestAmount
        • Outside Settlement: redeemFreeDocVendors
        • On Liquidation State: redeemAllDoc
        • How-to
    • Commission fees values
    • Vendors
    • Fees calculation
    • From outside the blockchain
      • Using RSK nodes
      • Using web3
      • Official Money on Chain ABIs
      • Events
      • Example code minting BPros
      • Example code minting BPros without Truffle
      • Example code redeeming BPros
      • Example code redeeming BPros without Truffle
      • Example code minting DOC
      • Example code redeeming free DOC
      • Example code redeeming DOC Request
      • Example code redeeming all DOC
  • Smart contracts
    • Contracts verification
    • ABIs documentation
      • BProToken
      • BtcPriceProviderMock
      • DocToken
      • ERC20Mintable
      • Governed
      • Initializable
      • MakeStoppable
      • MakeUnstoppable
      • MoC
      • MoCBProxManager
      • MoCBucketContainer
      • MoCConnector
      • MoCConverter
      • MoCEMACalculator
      • MoCExchange
      • MoCHelperLib
      • MoCHelperLibMock
      • MoCInrate
      • MoCLibConnection
      • MoCPriceProviderMock
      • MoCSettlement
      • MoCSettlementMock
      • MoCState
      • MoCStateMock
      • MoCToken
      • MoCVendors
      • MoCWhitelist
      • MockMakeStoppable
      • MockMakeUnstoppable
      • MockStopper
      • MockUpgradeDelegator
      • MockUpgraderTemplate
      • OwnerBurnableToken
      • Pausable
      • PriceFeed
      • PriceFeederAdder
      • PriceFeederRemover
      • PriceProvider
      • RevertingOnSend
      • Stoppable
      • Stopper
      • UpgradeDelegator
      • UpgraderTemplate
Powered by GitBook
On this page
  • Safe Math and precision
  • Inheritance, Composition and Contract whitelisting
  • Block gas limit prevention
  • Governance and Upgradability
  1. Money on Chain platform

Relevant patterns and choices

Safe Math and precision

MoC system requires many mathematical operations, in this model just the 2 basic operations are used (addition/subtraction, multiplication/division). To protect against overflows, OpenZeppelin SaveMath library is used on any of this operations. As current RSK EVM version does not "support" decimal values, it's also important to point out that in MoC every value that is mathematically a decimal, it's represented as an integer adjusted by a given value, which is called precision.

For example, let's take coverage formula: cob = nB / lB and suppose that on a given time nB=35 and lB=10, then cob = 35 / 10 = 3.5 if we look at the MoCHelperLib coverage method:

/**
  Coverage = nB / LB

  @dev Calculates Coverage
  @param nB Total BTC amount [using reservePrecision]
  @param lB Locked bitcoins amount [using reservePrecision]
  @return Coverage [using coveragePrecision]
**/
function coverage(MocLibConfig storage libConfig, uint256 nB, uint256 lB) public view
  returns(uint256) {
  if (lB == 0) {
    return UINT256_MAX;
  }

  return nB.mul(libConfig.coveragePrecision).div(lB);
}

We notice that:

  • nB and lB param are expected to be received with reservePrecision

  • coverage return value is supposed to be return with coveragePrecision

  • the actual formula first multiplies nB with the return coverage nB.mul(libConfig.coveragePrecision) and then dives by lB. The order is not trivial, as even if mathematically there is no difference, making the division first would result in precision lost.

In our example, supposing coveragePrecision = 1*10^18

cob = nB.mul(1*10^18).div(lB) = 35*10^17

If we invert the operation order:

cob = nB.div(lB).mul(1*10^18) = 3*10^18 ===> loosing precision !!!

There are many different precision values, depending on the value "denomination" being used, all of them are statically defined on the Library:

contract MoCHelperLibMock {
  ...
  constructor() public {
    mocLibConfig = MoCHelperLib.MocLibConfig({
      reservePrecision: 10 ** 18,
      mocPrecision: 10 ** 18,
      dayPrecision: 1
    });
  }

Even if many are equal, we keep them on separate variables to be able to adjust them accordantly on future formula changes. Using unsigned int256 as the norm for all values, sets an upper limit to ~76 decimal places, so even if it's ok to multiply 18 precision values a couple of times, we need to be careful not to overflow nor lose precision. Most of MoC methods signatures specify the expected precision of the given input and return values, as well of internal operation precision cancelling, for example:

  // [DISCOUNT] * [COV] / [COV] = [DISCOUNT]
  return bproLiqDiscountRate.mul(utpduCovDiff).div(utpduLiqDiff);

where the convention is to indicate the short description of the precision on brackets ([COV] = coveragePrecision).

Inheritance, Composition and Contract whitelisting

In general programming, Composition is preferred upon Inherence, but solidity presents new consideration to keep in mind when choosing each pattern. As composition means a new Contract, and that means intra-contracts calls, meaning public methods and confusing msg.sender scopes; one might be turn into diminish this and prioritize inherence. The problem then arises when contract code grows and deploy fees goes beyond block gas limit. Managing this equilibrium was not easy, and we think we are far from having the ultimate clearer and efficient solution yet, but using the whitelisted contract address network pattern, gave us an easy and scalable way on which to relay for contract inter-dependencies. We understand that this solution makes the system vulnerable on deploy stage, as there is a post deploy initilization phase that needs to be atomically completed in other to have the whole system ready, a hook in this process might be able to compromise it. A post deploy integrity check script might a good option to solve this in the future.

Block gas limit prevention

Although not recomended, dynamic array looping is needed to be performed on certain functions:

  • On Settlement, while processing DoCRedeemRequest or BProX collection.

That's why this functions are wrapped on TASKs and might requires more than one call to complete. They receive a step amount parameter indicating the maximum number of iterations to be performed on each call.

Note: Some model simulations had shown ~100 items is close to RSK block gas limit.

Governance and Upgradability

MoC contracts subscribes to a governance implementation that allows an external contract to authorize changers to:

  • Set single parameters values (for example, adjusting commission fee)

  • Upgrade specific contracts to new versions (for example updating some formula to make it more efficient)

  • Pause/Un-pause the whole system (intended as temporal halts for future upgrades)

PreviousContract mocksNextData dictionary

Last updated 2 years ago

⚠ This has been deprecated since the from the protocol was approved, however it is necessary to maintain the contracts and their documentation for legacy support.

For further detail on Governance mechanism refer to

Proposal to remove leveraged positions
Moc Governance project