Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
lidangzzz committed Feb 14, 2024
1 parent 2cadb36 commit d6376f3
Show file tree
Hide file tree
Showing 26 changed files with 345 additions and 388 deletions.
65 changes: 57 additions & 8 deletions darc-docs/docs/By-law Script/Getting Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import TabItem from '@theme/TabItem';

# Getting Started

## By-law Script = JavaScript + Operator Overloading
### By-law Script = JavaScript + Operator Overloading

By-law Script is the first programming language for describing the operations and rules for a DARC-based crypto company. It is a domain-specific language (DSL) that is designed to be easy to read and write, and to be used by non-programmers. It is based on JavaScript, and adds operator overloading to make it easier to write and read.

## Your First By-law Script Program
### Your First By-law Script Program

Here is a simple By-law Script program that defines the common stock of a company. Each share of common stock has voting weight 1 and dividend weight 1. This token class is called `token_0`, and the token index is 0.

Expand All @@ -26,9 +26,9 @@ batch_create_token_classes(
Next let's issue 1000 shares of `token_0` to the company's founder, 500 shares to Address_A, 400 shares to Address_B, and 100 shares to Address_C.

```javascript
cosnt Address_A = "0x1234567890123456789012345678901234567890";
cosnt Address_B = "0x1234567890123456789012345678901234567891";
cosnt Address_C = "0x1234567890123456789012345678901234567892";
cosnt Address_A = "0x123...";
cosnt Address_B = "0x51c...";
cosnt Address_C = "0x374...";
batch_mint_tokens(
[ Address_A, Address_B, Address_C], // the addresses of the recipients
[0,0,0], // the token index
Expand Down Expand Up @@ -59,8 +59,57 @@ Finally, Address_C wants to issue dividends to all token holders. The following
offer_dividends();
```

## Package Multiple Operations into a Program
### Package Operations into a Program

## Your First Plugin as a Law
The above examples of code all execute single operations. For a program, it can contain multiple operations, and all operations will be executed sequentially, one after another. The advantage of doing this is that if an operator needs to execute a program and the program consists of multiple operations, it is necessary to ensure that all operations contained in this program are successfully approved for execution by voting, or the entire program is rejected as a whole.

A plugin is an object that defines
Here is the translation of the example you provided:

**Address_E decides to invest in DARC. The investment agreement needs to complete four tasks**:

1. Address_E pays 50000000 wei as venture capital.
2. Address_E will receive 10000 shares of level-0 tokens (common stock).
3. Address_E will receive 1 share of level-1 tokens (board seat).
4. Address_E will receive 20000 shares of level-2 tokens (dividendable-only stock)."


For the aforementioned four operations, we aspire for either all four operations to be simultaneously approved and successfully executed, or all four operations to be simultaneously rejected with none executed. For investor Address_E, it is absolutely undesirable to have a scenario where a single-operation program pays 50000000 wei to DARC, followed by the subsequent rejection of the three operations by the DARC manager. Therefore, in this scenario, the four operations must be bundled into a single program. If this program requires voting, the entire program must undergo the voting process. Upon rejection, Address_E will neither acquire shares nor a board seat, and the cash will be refunded to Address_E.

Below is a complete By-law Script Program containing the four operations mentioned above:

```javascript
// pay 50000000 wei to DARC
pay_cash(
50000000, // the amount = 50000000 wei
0, // the payment type = 0, the default native token
0); // the dividendable flag, 0 means the payment is non-dividendable

// mint 10000 shares of level-0,
// 1 share of level-1,
// and 20000 shares of level-2 tokens to Address_E
batch_mint_tokens(
[Address_E, Address_E, Address_E], // the addresses of the recipients
[0, 1, 2], // the token index
[10000, 1, 20000]); // the amounts

```

This script encapsulates all the operations into a single program, ensuring that they are either all approved and executed successfully or all rejected without any execution. If the program requires voting, it must undergo the voting process as a whole. If rejected, Address_E will not obtain shares, a board seat, nor pay the cash, which will be refunded to Address_E.

### Your First Plugin as a Law

Plugin is the core mechanism of DARC and serves as its legal framework. All rules within DARC are based on the plugin system. By-law Script supports operator overload to make the composition and design of plugins simpler and more convenient. In By-law Script, each plugin is an object body. Below is the simplest example:

```javascript
const plugin_0 ={
returnType: NO, // return type: NO
level: 3, // level 3
votingRuleIndex: 0,
notes: "disable all program",
bIsEnabled: true,
bIsBeforeOperation: true,
conditionNodes: new TRUE() // always true
},
```

In the plugin
20 changes: 20 additions & 0 deletions darc-js/src/SDK/includes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,26 @@ import {
OPCODE_ID_37_UPGRADE_TO_THE_LATEST
} from "./opcodes/opcodeTable";

/**
* Below are return types
*/
export let UNDEFINED = 0;
export let SANDBOX_NEEDED = 1;
export let NO = 2;
export let VOTING_NEEDED = 3;
export let YES_AND_SKIP_SANDBOX = 4;
export let YES = 5;

export enum EnumReturnType {
UNDEFINED = 0,
SANDBOX_NEEDED = 1,
NO = 2,
VOTING_NEEDED = 3,
YES_AND_SKIP_SANDBOX = 4,
YES = 5
}


/**
* The list of operations to be executed
* When an operation function is called, it will add an operation to this list
Expand Down
1 change: 0 additions & 1 deletion darc-js/src/SDK/opcodes/pluginProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export function pluginProcessor(pluginArray: PluginStruct[] | PluginStructWithNo
votingRuleIndex: pluginArray[i].votingRuleIndex,
notes: pluginArray[i].notes,
bIsEnabled: pluginArray[i].bIsEnabled,
bIsInitialized: pluginArray[i].bIsInitialized,
bIsBeforeOperation: pluginArray[i].bIsBeforeOperation,
});
}
Expand Down
29 changes: 2 additions & 27 deletions darc-js/src/darcBinary/DARC-latest.json

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions darc-js/src/darcjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@ import { OperationStruct, OperationStructOutput, ProgramStruct, VotingRuleStruct
import {ethers} from "ethers";
import * as DARC from "./DARC/DARC";

/**
* Below are return types
*/
export const UNDEFINED = 0;
export const SANDBOX_NEEDED = 1;
export const NO = 2;
export const VOTING_NEEDED = 3;
export const YES_AND_SKIP_SANDBOX = 4;
export const YES = 5;

export enum EnumReturnType {
UNDEFINED = 0,
SANDBOX_NEEDED = 1,
NO = 2,
VOTING_NEEDED = 3,
YES_AND_SKIP_SANDBOX = 4,
YES = 5
}

import {
OPCODE_ID_1_BATCH_MINT_TOKENS,
OPCODE_ID_2_BATCH_CREATE_TOKEN_CLASSES,
Expand Down
3 changes: 0 additions & 3 deletions darc-js/src/types/basicTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export type PluginStruct = {
votingRuleIndex: PromiseOrValue<BigNumberish>;
notes: PromiseOrValue<string>;
bIsEnabled: PromiseOrValue<boolean>;
bIsInitialized: PromiseOrValue<boolean>;
bIsBeforeOperation: PromiseOrValue<boolean>;
};

Expand All @@ -108,7 +107,6 @@ export type PluginStructWithNode = {
votingRuleIndex: PromiseOrValue<BigNumberish>;
notes: PromiseOrValue<string>;
bIsEnabled: PromiseOrValue<boolean>;
bIsInitialized: PromiseOrValue<boolean>;
bIsBeforeOperation: PromiseOrValue<boolean>;
};

Expand All @@ -128,7 +126,6 @@ export type PluginStructOutput = [
votingRuleIndex: BigNumber;
notes: string;
bIsEnabled: boolean;
bIsInitialized: boolean;
bIsBeforeOperation: boolean;
};

Expand Down
2 changes: 0 additions & 2 deletions darc-js/tests/runtime-test/transpileAndRun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ describe('transpile and execution test', () => {
votingRuleIndex: BigNumber.from(0),
notes: "disable all program",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: true,
conditionNodes: new TRUE() // always true
},
Expand All @@ -77,7 +76,6 @@ describe('transpile and execution test', () => {
votingRuleIndex: BigInt(0),
notes: "allow operatorAddress == target1 | operatorAddress == target2",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: true,
conditionNodes:
or(
Expand Down
3 changes: 0 additions & 3 deletions darc-js/tests/sdk-test/sdk-node-generation-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ describe('SDK node generation test', () => {
votingRuleIndex: BigNumber.from(0),
notes: "disable all program",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: true,
conditionNodes:[{
id: BigNumber.from(0),
Expand All @@ -89,7 +88,6 @@ describe('SDK node generation test', () => {
votingRuleIndex: BigInt(0),
notes: "allow operatorAddress == target1 | operatorAddress == target2",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: true,
conditionNodes:
or(
Expand Down Expand Up @@ -221,7 +219,6 @@ describe('SDK node generation test', () => {
votingRuleIndex: BigInt(0),
notes: "allow operatorAddress == target1 | operatorAddress == target2",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: true,
conditionNodes:
or(
Expand Down
2 changes: 0 additions & 2 deletions darc-js/tests/sdk-test/sdk-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ describe('SDK execution test', () => {
votingRuleIndex: BigNumber.from(0),
notes: "disable all program",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: true,
conditionNodes:[{
id: BigNumber.from(0),
Expand All @@ -141,7 +140,6 @@ describe('SDK execution test', () => {
votingRuleIndex: BigInt(0),
notes: "allow operatorAddress == target1 | operatorAddress == target2",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: true,
conditionNodes:[
// node 0: boolean operator OR
Expand Down
2 changes: 0 additions & 2 deletions darc-protocol/contracts/protocol/MachineStateManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ contract MachineStateManager {
0,
"",
true,
true,
true
));

Expand Down Expand Up @@ -154,7 +153,6 @@ contract MachineStateManager {
0,
"",
true,
true,
false
));

Expand Down
5 changes: 0 additions & 5 deletions darc-protocol/contracts/protocol/Plugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,6 @@ struct Plugin {
*/
bool bIsEnabled;

/**
* the boolean that indicates whether the plugin is deleted or not
*/
bool bIsInitialized;

/**
* the boolean that indicates whether the plugin is a before operation
* plugin or after operation plugin
Expand Down
6 changes: 0 additions & 6 deletions darc-protocol/contracts/protocol/Plugin/PluginFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,9 @@ contract PluginFactory is ConditionExpressionFactory{
if (bIsBeforeOperation)
{
require(pluginIndex < currentMachineState.beforeOpPlugins.length, "PluginFactory: plugin index out of range");
if (currentMachineState.beforeOpPlugins[pluginIndex].bIsInitialized == false) {
return (returnLevel, returnType, returnVotingRuleIndex);
}
}
else {
require(pluginIndex < currentMachineState.afterOpPlugins.length, "PluginFactory: plugin index out of range");
if (currentMachineState.afterOpPlugins[pluginIndex].bIsInitialized == false) {
return (returnLevel, returnType, returnVotingRuleIndex);
}
}

// start from expression condition root node idx = 0, recursively check the condition expression tree
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,24 +104,20 @@ contract PluginInstructions is MachineStateManager{
if (bIsSandbox) { // if running in sandbox
if (operation.param.PLUGIN_ARRAY[i].bIsBeforeOperation) { // if it is a before operation plugin
sandboxMachineState.beforeOpPlugins.push(operation.param.PLUGIN_ARRAY[i]);
sandboxMachineState.beforeOpPlugins[sandboxMachineState.beforeOpPlugins.length-1].bIsInitialized = true;
sandboxMachineState.beforeOpPlugins[sandboxMachineState.beforeOpPlugins.length-1].bIsEnabled = false;
}
else { // if it is an after operation plugin
sandboxMachineState.afterOpPlugins.push(operation.param.PLUGIN_ARRAY[i]);
sandboxMachineState.afterOpPlugins[sandboxMachineState.afterOpPlugins.length-1].bIsInitialized = true;
sandboxMachineState.afterOpPlugins[sandboxMachineState.afterOpPlugins.length-1].bIsEnabled = false;
}
}
else {
if (operation.param.PLUGIN_ARRAY[i].bIsBeforeOperation) { // if it is a before operation plugin
currentMachineState.beforeOpPlugins.push(operation.param.PLUGIN_ARRAY[i]);
currentMachineState.beforeOpPlugins[currentMachineState.beforeOpPlugins.length-1].bIsInitialized = true;
currentMachineState.beforeOpPlugins[currentMachineState.beforeOpPlugins.length-1].bIsEnabled = false;
}
else { // if it is an after operation plugin
currentMachineState.afterOpPlugins.push(operation.param.PLUGIN_ARRAY[i]);
currentMachineState.afterOpPlugins[currentMachineState.beforeOpPlugins.length-1].bIsInitialized = true;
currentMachineState.afterOpPlugins[currentMachineState.beforeOpPlugins.length-1].bIsEnabled = false;
}
}
Expand All @@ -143,24 +139,20 @@ contract PluginInstructions is MachineStateManager{
if (bIsSandbox) { // if running in sandbox
if (operation.param.PLUGIN_ARRAY[i].bIsBeforeOperation) { // if it is a before operation plugin
sandboxMachineState.beforeOpPlugins.push(operation.param.PLUGIN_ARRAY[i]);
sandboxMachineState.beforeOpPlugins[sandboxMachineState.beforeOpPlugins.length-1].bIsInitialized = true;
sandboxMachineState.beforeOpPlugins[sandboxMachineState.beforeOpPlugins.length-1].bIsEnabled = true;
}
else { // if it is an after operation plugin
sandboxMachineState.afterOpPlugins.push(operation.param.PLUGIN_ARRAY[i]);
sandboxMachineState.afterOpPlugins[sandboxMachineState.afterOpPlugins.length-1].bIsInitialized = true;
sandboxMachineState.afterOpPlugins[sandboxMachineState.afterOpPlugins.length-1].bIsEnabled = true;
}
}
else {
if (operation.param.PLUGIN_ARRAY[i].bIsBeforeOperation) { // if it is a before operation plugin
currentMachineState.beforeOpPlugins.push(operation.param.PLUGIN_ARRAY[i]);
currentMachineState.beforeOpPlugins[currentMachineState.beforeOpPlugins.length-1].bIsInitialized = true;
currentMachineState.beforeOpPlugins[currentMachineState.beforeOpPlugins.length-1].bIsEnabled = true;
}
else { // if it is an after operation plugin
currentMachineState.afterOpPlugins.push(operation.param.PLUGIN_ARRAY[i]);
currentMachineState.afterOpPlugins[currentMachineState.beforeOpPlugins.length-1].bIsInitialized = true;
currentMachineState.afterOpPlugins[currentMachineState.beforeOpPlugins.length-1].bIsEnabled = true;
}
}
Expand All @@ -183,13 +175,11 @@ contract PluginInstructions is MachineStateManager{
if (bIsSandbox) { // if running in sandbox
if (bIsBeforeOpPlugins[i]) { // if it is a before operation plugin
require(pluginIndexes[i] < sandboxMachineState.beforeOpPlugins.length, "Invalid plugin index to be enabled"); // require that the plugin index is less than the length of the before operation plugins array
require(sandboxMachineState.beforeOpPlugins[pluginIndexes[i]].bIsInitialized, "The plugin to be enabled is not initialized");
require(!sandboxMachineState.beforeOpPlugins[pluginIndexes[i]].bIsEnabled, "The plugin to be enabled is already enabled");
sandboxMachineState.beforeOpPlugins[pluginIndexes[i]].bIsEnabled = true;
}
else { // if it is an after operation plugin
require(pluginIndexes[i] < sandboxMachineState.afterOpPlugins.length, "Invalid plugin index to be enabled"); // require that the plugin index is less than the length of the after operation plugins array
require(sandboxMachineState.afterOpPlugins[pluginIndexes[i]].bIsInitialized, "The plugin to be enabled is not initialized");
require(!sandboxMachineState.afterOpPlugins[pluginIndexes[i]].bIsEnabled, "The plugin to be enabled is already enabled");
sandboxMachineState.afterOpPlugins[pluginIndexes[i]].bIsEnabled = true;
}
Expand All @@ -198,13 +188,11 @@ contract PluginInstructions is MachineStateManager{
else {
if (bIsBeforeOpPlugins[i]) { // if it is a before operation plugin
require(pluginIndexes[i] < currentMachineState.beforeOpPlugins.length, "Invalid plugin index to be enabled"); // require that the plugin index is less than the length of the before operation plugins array
require(currentMachineState.beforeOpPlugins[pluginIndexes[i]].bIsInitialized, "The plugin to be enabled is not initialized");
require(!currentMachineState.beforeOpPlugins[pluginIndexes[i]].bIsEnabled, "The plugin to be enabled is already enabled");
currentMachineState.beforeOpPlugins[pluginIndexes[i]].bIsEnabled = true;
}
else { // if it is an after operation plugin
require(pluginIndexes[i] < currentMachineState.afterOpPlugins.length, "Invalid plugin index to be enabled"); // require that the plugin index is less than the length of the after operation plugins array
require(currentMachineState.afterOpPlugins[pluginIndexes[i]].bIsInitialized, "The plugin to be enabled is not initialized");
require(!currentMachineState.afterOpPlugins[pluginIndexes[i]].bIsEnabled, "The plugin to be enabled is already enabled");
currentMachineState.afterOpPlugins[pluginIndexes[i]].bIsEnabled = true;
}
Expand All @@ -228,13 +216,11 @@ contract PluginInstructions is MachineStateManager{
if (bIsSandbox) { // if running in sandbox
if (bIsBeforeOpPlugins[i]) { // if it is a before operation plugin
require(pluginIndexes[i] < sandboxMachineState.beforeOpPlugins.length, "Invalid plugin index to be disabled"); // require that the plugin index is less than the length of the before operation plugins array
require(sandboxMachineState.beforeOpPlugins[pluginIndexes[i]].bIsInitialized, "The plugin to be disabled is not initialized");
require(sandboxMachineState.beforeOpPlugins[pluginIndexes[i]].bIsEnabled, "The plugin to be disabled is already disabled");
sandboxMachineState.beforeOpPlugins[pluginIndexes[i]].bIsEnabled = false;
}
else { // if it is an after operation plugin
require(pluginIndexes[i] < sandboxMachineState.afterOpPlugins.length, "Invalid plugin index to be disabled"); // require that the plugin index is less than the length of the after operation plugins array
require(sandboxMachineState.afterOpPlugins[pluginIndexes[i]].bIsInitialized, "The plugin to be disabled is not initialized");
require(sandboxMachineState.afterOpPlugins[pluginIndexes[i]].bIsEnabled, "The plugin to be disabled is already disabled");
sandboxMachineState.afterOpPlugins[pluginIndexes[i]].bIsEnabled = false;
}
Expand All @@ -243,7 +229,6 @@ contract PluginInstructions is MachineStateManager{
else {
if (bIsBeforeOpPlugins[i]) { // if it is a before operation plugin
require(pluginIndexes[i] < currentMachineState.beforeOpPlugins.length, "Invalid plugin index to be disabled"); // require that the plugin index is less than the length of the before operation plugins array
require(currentMachineState.beforeOpPlugins[pluginIndexes[i]].bIsInitialized, "The plugin to be disabled is not initialized");
require(currentMachineState.beforeOpPlugins[pluginIndexes[i]].bIsEnabled, "The plugin to be disabled is already disabled");
currentMachineState.beforeOpPlugins[pluginIndexes[i]].bIsEnabled = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ contract VotingTest is Runtime {
// votingRuleIndex: 0,
// notes: "test",
// bIsEnabled: true,
// bIsInitialized: true,
// bIsBeforeOperation: true
// });

Expand All @@ -86,7 +85,6 @@ contract VotingTest is Runtime {
votingRuleIndex: 0,
notes: "test",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: true
}));

Expand Down Expand Up @@ -126,7 +124,6 @@ contract VotingTest is Runtime {
votingRuleIndex: 0,
notes: "test",
bIsEnabled: true,
bIsInitialized: true,
bIsBeforeOperation: false
}));

Expand Down
Loading

0 comments on commit d6376f3

Please sign in to comment.