Melon Protocol Implementation
Switch branches/tags
Clone or download
Latest commit da70de6 Dec 16, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin Logging Dec 14, 2018
deployments Deploy to KOVAN Dec 14, 2018
legacy Merge changes develop and fix merge errors Dec 14, 2018
logs Add winston file logger Dec 5, 2018
src Merge pull request #632 from melonproject/fix-cancel-zeroex Dec 15, 2018
.babelrc Re-adding ava. Nov 28, 2018
.doxityrc Help doxity build command find submodules Jan 11, 2018
.editorconfig Migrate token functions from contract-lab Oct 11, 2018
.gitattributes Migrate token functions from contract-lab Oct 11, 2018
.gitignore Option to deploy tokens Dec 12, 2018
.npmignore Cleanup of imports and adding rollup. Nov 27, 2018
.prettierrc Add prettier, tslint Oct 11, 2018
.snyk Add snyk to CI Nov 30, 2018
.solcover.js Fix coverage test command Aug 17, 2017
.soliumignore Rename to third-party / thirdParty. (#628) Dec 13, 2018
.soliumrc.json Add solidity function ordering linter rule Jan 4, 2018
.travis.yml Log all the logs on CI Dec 13, 2018
CHANGELOG.md Merge remote-tracking branch 'origin/develop' into refactor Oct 23, 2018
CONTRIBUTING.md Merge pull request #409 from melonproject/develop Feb 27, 2018
LICENSE Initial commit Nov 4, 2016
PULL_REQUEST_TEMPLATE Update PULL_REQUEST_TEMPLATE Jun 8, 2018
README.md Concretisize pattern, add Events for hub/spokes Dec 7, 2018
jest.config.js Fixing jest test reports. Dec 5, 2018
jest.setup.js Adding getTokenBySymbol utility function. Dec 10, 2018
package.json Merge remote-tracking branch 'origin/develop' into fix-cancel-zeroex Dec 15, 2018
rollup.config.js Cleanup of imports and adding rollup. Nov 27, 2018
tsconfig.json Merge branch 'develop' into do-todos Dec 13, 2018
tslint.json Disable tslint line length for imports Dec 6, 2018
typings.d.ts Integrate contract-lab ... first steps Oct 11, 2018
yarn.lock Merge remote-tracking branch 'origin/develop' into fix-cancel-zeroex Dec 15, 2018

README.md

Melon Protocol

Gitter chat Build Status Solidity version License: GPL v3 Dependencies Development Dependencies

Melon ([méllō], μέλλω; Greek for "destined to be") is blockchain software that seeks to enable participants to set up, manage and invest in technology regulated investment funds in a way that reduces barriers to entry, while minimizing the requirements for trust.

It does so by leveraging the fact that digital assets on distributed quasi-Turing Complete machines can be held solely by smart-contract code, and spent only according to preprogrammed rules within this code. The Melon protocol is a set of rules for how digital assets can be spent once held in a Melon smart-contract, or a Melon investment fund. These rules are meant to protect the investor and fund manager from malevolent behaviour of each other, even when both parties remain private.

Melon is to investment funds as Bitcoin is to accounting: a set of rules, enforced by blockchain technology, legitimized by the consent of its participants.

This repository contains a reference implementation of the Melon protocol written in Solidity, as specified in our paper.

Get started

Prerequisites

  • Yarn

Installation

# Clone this repository
git clone git@github.com:melonproject/protocol.git
cd protocol
# Install dependencies
yarn install

If you don't set JSON_RPC_ENDPOINT, the test will load ganache in-memory which works but is much slower.

Deployment and testing

After installation, go to the above protocol directory, open a terminal and:

# Generate bytecode and abi of smart-contracts
yarn compile
# Launch parity dev chain:
yarn devchain
# Open a second terminal and deploy the contracts to the development network:
yarn deploy (Not working yet)
# Run the tests using
yarn test (Not working yet)

Alternatives

Kovan Deployment

After installation is complete, go to the above protocol directory, open a terminal and:

# Launch an ethereum client. For example something similar to this:
parity \
  --chain kovan      \
  --rpcport 8545     \
  --auto-update=all  \
  --jsonrpc-apis=all \
  --author <address> \
  --unlock <address> \
  --password <password file>

# Open a second terminal and deploy the contracts:
npm run deploy:kovan

Use it as a consumer

To integrate the Melon Protocol into your application, you do not need to clone this repo, you can just install it from npm:

yarn add @melonproject/protocol

You need to have a local dev-chain running to develop your consuming application. We recommend Ganache:

yarn add -D ganache-cli
yarn ganache-cli --gasLimit 0x7a1200 --defaultBalanceEther 1000000

Then, you can deploy the contracts to your local dev node:

yarn melon deploy

This creates a new deployment which you can use like this:

import * as protocol from '@melonproject/protocol';

const environment = await protocol.utils.environment.initTestEnvironment();
const deployment = protocol.utils.solidity.getDeployment(environment);
const hub = await protocol.factory.managersToHubs(
  deployment.fundFactory,
  '0xdeadbeef',
  environment,
);

Development Tips

Using the logger

To help debug the system, the test environment has a test logger that logs into ./logs/. This keeps the terminal clean but also a great possibility to inspect the logs in detail. Here is how it works:

Inside a function that has the environment, the environment.logger is a curried function with the following signature:

(namespace: string, level: LogLevels, ...messages: any): void;

This currying gives a high level of flexibility, but basically we just use this pattern:

const debug = environment.logger('melon:protocol:utils', LogLevels.DEBUG);

// and then use debug as you would console.log:

debug('Something happened', interestingObject, ' ... and more ...', whatever);

Deconstruct a transaction from the transactionFactory

Generally, transactions have a shortcut method called execute, which is renamed to the actual transaction name:

import { transfer } from '~/contracts/dependencies/token/transactions/transfer';

const params = {
  howMuch: createQuantity(shared.token, 2000000),
  to: shared.accounts[1],
};

await transfer(params);

If one needs to have custom access to the different steps, like a custom signer, the transaction function can be decomposed into a prepare and sign step:

import { sign } from '~/utils/environment/sign';

const prepared = await transfer.prepare(params);

const signedTransactionData = await sign(prepared.rawTransaction, environment);

const result = await transfer.send(signedTransactionData, params);

Skip gas estimation preflight/guards

Sometimes during development, one wants to check if a transaction actually fails without the guards. To do so, there are options inside of the transaction factory. The simplest example would be transfer. So here is the minimalistic usage of transfer with skipped guards and transactions:

import { transfer } from '~/contracts/dependencies/token/transactions/transfer';

const params = {
  howMuch: createQuantity(shared.token, 2000000),
  to: shared.accounts[1],
};

await transfer(params, environment, {
  gas: '8000000',
  skipGasEstimation: true,
  skipGuards: true,
});

The same pattern could be applied to the deconstructed execute:

import { sign } from '~/utils/environment/sign';

const options = {
  gas: '8000000',
  skipGasEstimation: true,
  skipGuards: true,
};

const prepared = await transfer.prepare(params, options);

const signedTransactionData = await sign(prepared.rawTransaction, environment);

const result = await transfer.send(signedTransactionData, params);

Events

Main principle: Every smart contract should be seen as an event-sourced entity:

  • It has one current state. We can query the current state through calls.
  • This current state is the result of an initial state and a list of transactions that altered that state. When the state of a smart contract changes, it should emit events in a fashion that an external observer can reproduce the state of the smart contract from every point in history only by observing the emitted events.

In other words: Events should transport as much information as needed so that an observer can sync for example a database.

How to do this:

  1. Define the shape of the state of a smart contract
  2. Define possible changes to that state
  3. Emit events when that state changes.

Example ERC20

  1. Shape of state:
mapping (address => uint256) balances;
  1. Possible changes:
  • Someone sends somebody an amount: Transfer
  1. Emit events: It is obvious for that example, but lets see what an observer can see the following events and reproduce every step in history.

For the sake of simplicity, lets assume that: 0x0: is the null address 0x1: user 1 0x2: user 2 ...and so on

Transfer(0x0, 0x1, 100) // Initial minting: User 1 receives 100 tokens. Total 100 tokens.
Transfer(0x1, 0x2, 30) // User 1 sends 30 tokens to user 2. New balances: User 1: 70, User 2: 30.
...

Although we fire events after the action happened, we use nouns in the event names. So: NewFund instead of FundCreated of CreateFund.

Like we communicate to the outside world: Hey, there is a NewFund.

Troubleshooting

Permission denied (publickey) when cloning the repo

Try cloning using git clone https://github.com/melonproject/smart-contracts.git

Spec json is invalid when running Parity Devchain

Update your Parity installation to the latest version or try changing "instantSeal": null to "instantSeal": { "params": {} } in chainGenesis.json

Stuck at deploy step

Deploying contracts may stuck indefinitely in case your parity node is not unlocked for some reason. Locked node requires you to enter password for each transaciton manually.

Contributing

As an open-source project, we welcome any kind of community involvement, whether that is by contributing code, reporting issues or engaging in insightful discussions. Please see our contributing instructions for information on the code style we use.

Security Issues

If you find a vulnerability that may affect live or testnet deployments please send your report privately to security@melonport.com. Please DO NOT file a public issue.

Protocol Design

When considering protocol design proposals, we are looking for:

  • A description of the problem this design proposal solves
  • Discussion of the tradeoffs involved
  • Review of other existing solutions
  • Links to relevant literature (RFCs, papers, etc)
  • Discussion of the proposed solution

Please note that protocol design is hard, and meticulous work. You may need to review existing literature and think through generalized use cases.

Implementation Design

When considering design proposals for implementations, we are looking for:

  • A description of the problem this design proposal solves
  • Discussion of the tradeoffs involved
  • Discussion of the proposed solution