andreclaro / tokenized-funds

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ondo CASH & CASH+ Protocol

Overview

Ondo's Cash protocol allows for whitelisted (KYC'd) user to hold exposure to Real World Assets (RWAs) on chain.


Framework Overview

  • Unit Testing - Foundry
  • Fuzz Testing - Foundry
  • Invariant Testing - Echidna
  • Deployment & Scripting - Hardhat

Env Setup and Testing

Create an .env file in this repositories root directory and populate the variables listed below

The RPC URLS can be generated by setting up free alchemy

ETHEREUM_RPC_URL='https://eth-mainnet.alchemyapi.io/v2/...'
GOERLI_RPC_URL='https://eth-goerli.g.alchemy.com/v2/...'
POLYGON_RPC_URL='https://polygon-mainnet.g.alchemy.com/v2/...'
MNEMONIC='test test test test ...'
FORK_FROM_BLOCK_NUMBER=15958078
ETHERSCAN_API_KEY='' 
REPORT_GAS = true
MAINNET_PRIVATE_KEY=''
TESTNET_PRIVATE_KEY=''
FORGE_API_KEY_ETHEREUM = https://eth-mainnet.alchemyapi.io/v2/

Install foundry:

cargo install --git https://github.com/foundry-rs/foundry --profile local --locked foundry-cli anvil

To run unit tests:

yarn test-forge

To run an individual test file:

yarn test-forge --match-path <RELATIVE_PATH_TO_TEST_FILE>

To run tests and receive a gas report:

yarn test-forge --gas-report

Running a Local Ethereum Node

Ensure that your .env file is setup as described in, Env Setup and Testing

To start a Hardhat local node:

yarn local-node 

Once the node is running you can run Hardhat scripts in a separate terminal to interact with and modify the state of the local blockchain. For example:

yarn hardhat run --network localhost scripts/ci/event_coverage.ts

The script scripts/ci/event_coverage.ts aims to exercise the contracts such that all possible event types are emitted.

It is very useful for testing the subgraph and frontend, and it's a great example for how to write your own scripts.

The script is hardcoded to point to a node at http://127.0.0.1:8545, which may need to be modified.


Deployment

We use the hardhat-deploy community plugin for local node deployments and unit testing.

There are two sets of deployment files

  • local: Used for deploying to localhost

  • production: Used for deploying to mainnet

Each set of deployment files has a set of deploy scripts for each CASH instance (CASH, CashKYCSender, CashKYCSenderReceiver). Each of these instances deploys a CASH token and a corresponding CashManager. The latter two tokens (CashKYCSender, CashKYCSenderReceiver) must be deployed after the kycRegistry is deployed. After deployment, each CASH instance has a corresponding post deploy script (deploy_cash, deploy_cashKYCSender, deploy_cashKYCSenderReceiver) which permissions roles on Defender and deploys tokens from the factory contracts.


Foundry testing

For testing with Foundry, forge-tests/BasicDeployment.sol was added to allow for users to easily deploy and setup the CASH/CASH+ dapp for local testing.

To test contracts within foundry from a deployed state please include the following layout within your testing file.

pragma solidity 0.8.16;

import "forge-tests/BasicDeployment.sol";

contract TestCashManager_Cash is BasicDeployment {
  function setUp() public {
    createDeploymentCash();
  }
  function testName() public {
    console.log(cashProxied.name());
  }
}
 

Testing with Echidna

Install Echidna here

To run tests:

yarn clean && yarn compile && echidna-test . --contract E2E --config contracts/echidna/config.yaml

Expected output: Screenshot 2022-11-02 at 12 05 15 PM


KYC Registry signature validation

Ondo's KYC Registry has an external function, addKYCAddressViaSignature, that allows an external actor to add an user to the KYC Registry for a specific group. This function takes in a signature of a message digest computed from the attributes {user, KYC requirement group, deadline} and verifies that it has been signed by a wallet that has been whitelisted in the access control functionality of the KYC Registry.

Please see the sample typescript code for how message can be computed in order to create a signature that the KYC Registry can validate and allow external actors to add to KYC registry.

  const domain = {
    name: "OndoKYCRegistry",
    version: "1",
    chainId: 1,
    verifyingContract: "<KYCRegistry Address>",
  };
  // The named list of all type definitions
  const types = {
    KYCApproval: [
      { name: "kycRequirementGroup", type: "uint256" },
      { name: "user", type: "address" },
      { name: "deadline", type: "uint256" },
    ],
  };
  // The data to sign
  const value = {
    kycRequirementGroup: "<group number>",
    user: "<user address to add>",
    deadline: "500",
  };
  console.log(ethers.utils._TypedDataEncoder.hash(domain, types, value));

The output of the above is an EIP 712 compliant digest. We will use an OZ defender relayer as the signer. (See https://docs.openzeppelin.com/defender/relay-api-reference#sign-typed-data-endpoint for more). A successful signature will result in a response similar to:

{'r': '0xbedbf96ab9d59ad2178d8fcb18588897c854f92a065f0347925f1387b4c38fe7',
's': '0x72ca0c2d966ff214800d80c74f4301bf6230bcc95d488470bb1da8ee1f76c0f6',
'v': 37,
...}

Please note that ecrecover (which the Registry uses) requires V be 27 or 28 So a conversion must be applied before interacting with addKYCAddressViaSignature


Running Slither (a Static Analyzer for Solidity)

Python must be installed. Open a terminal and run:

pip3 install slither-analyzer

To run slither on a specific contract run the following in terminal:

yarn slither-check contracts/CashManager.sol

About

License:Other


Languages

Language:Solidity 99.1%Language:TypeScript 0.9%Language:Makefile 0.1%Language:Nix 0.0%Language:JavaScript 0.0%