Skip to content

Commit

Permalink
Merge branch 'dev-protocol-sandbox'
Browse files Browse the repository at this point in the history
  • Loading branch information
lidangzzz committed May 30, 2023
2 parents ae70d5c + 98427c0 commit 0657011
Show file tree
Hide file tree
Showing 16 changed files with 829 additions and 23 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ years by limiting the `set_parameters()` function.
const dividend_yield_rate_law = {
condition:
(operation == "set_parameters") & // operation is "set_parameters"
(set_parameters_key == "dividentPermyriadPerTransaction") & // the key is "dividend_yield_rate"
(set_parameters_key == "dividendPermyriadPerTransaction") & // the key is "dividend_yield_rate"
(set_parameters_value < 500) & // the value is < 500‱ (5%)
(timestamp < 1893477600), // the timestamp < unix timestamp 2030-01-01 00:00:00 (UTC)

Expand Down Expand Up @@ -510,7 +510,7 @@ Since Hardhat and OpenZeppelin are used, the project can be built using the foll
2. Compile the contracts

```shell
npm run compile
npx hardhat compile
```

3. Run the Darc test network
Expand All @@ -522,7 +522,7 @@ Since Hardhat and OpenZeppelin are used, the project can be built using the foll
4. Test contracts

```shell
npm run test
npx hardhat test
REPORT_GAS=true npm run test
```

Expand Down
2 changes: 1 addition & 1 deletion README_cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ dividend_X
const dividend_yield_rate_law = {
condition:
(operation == "set_parameters") & // 操作指令是 "set_parameters"
(set_parameters_key == "dividentPermyriadPerTransaction") & // 设置参数的键值为 "dividend_yield_rate"
(set_parameters_key == "dividendPermyriadPerTransaction") & // 设置参数的键值为 "dividend_yield_rate"
(set_parameters_value < 500) & // the value is < 500‱ (5%)
(timestamp < 1893477600), // 时间戳小于 < unix timestamp 2030-01-01 00:00:00 (UTC)

Expand Down
23 changes: 23 additions & 0 deletions darc-protocol/contracts/Dashboard/Dashboard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,27 @@ contract Dashboard is MachineStateManager {
function getMyInfo() public view returns (address) {
return msg.sender;
}

/**
* The getter function of total voting weight for a token class
* @param tokenClassIndex The index of the token class
*/
function sumVotingWeightByTokenClass(uint256 tokenClassIndex) public view returns (uint256) {
return sumVotingWeightForTokenClass(false, tokenClassIndex);
}

/**
* The getter function of total dividend weight for a token class
* @param tokenClassIndex The index of the token class
*/
function sumDividendWeightByTokenClass(uint256 tokenClassIndex) public view returns (uint256) {
return sumDividendWeightForTokenClass(false, tokenClassIndex);
}

/**
* Get the current dividend per unit
*/
function getCurrentDividendPerUnit() public view returns (uint256) {
return currentDividendPerUnit(false);
}
}
13 changes: 11 additions & 2 deletions darc-protocol/contracts/MachineState.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ struct MachineStateParameters{
* For each dividend cycle, the dividend will be distributed to all the token owners
* The dividend will be calculated by the following formula:
* currentCashBalanceForDividends +=
* NEW_TRANSACTION_INCOME * dividentPermyriadPerTransaction / 10000
* NEW_TRANSACTION_INCOME * dividendPermyriadPerTransaction / 10000
* */
uint256 dividentPermyriadPerTransaction;
uint256 dividendPermyriadPerTransaction;

/**
* @notice the dividend cycle of the DARC protocol
Expand Down Expand Up @@ -82,6 +82,15 @@ struct MachineStateParameters{
* or tokens/NFTs for the token owners
*/
string[] strStorageList;

/**
* @notice The list of the active emergency agents
* The emergency agents can be used to do all emergency operations
* of the DARC protocol
*/
address[] activeEmergencyAgentsAddressList;

bool bIsEmergency;
}

/**
Expand Down
200 changes: 197 additions & 3 deletions darc-protocol/contracts/MachineStateManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ pragma solidity ^0.8.9;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./MachineState.sol";
import "./Plugin/Plugin.sol";
import "./Utilities/ErrorMsg.sol";

// import openzeppelin upgradeable contracts safe math
import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol";
/**
* @title DARC Machine State Manager
* @author DARC Team
Expand Down Expand Up @@ -54,6 +58,11 @@ contract MachineStateManager {
* @notice the finite state
*/
FiniteState public finiteState;

/**
* Parameters and configs
*/
uint256 dividendBufferSize;



Expand All @@ -68,6 +77,8 @@ contract MachineStateManager {

currentMachineState.beforeOpPlugins = new Plugin[](0);
currentMachineState.afterOpPlugins = new Plugin[](0);

dividendBufferSize = 10000;

/**
* Todo:
Expand All @@ -91,7 +102,7 @@ contract MachineStateManager {
);
currentMachineState.beforeOpPlugins.push(Plugin(
EnumReturnType.YES_AND_SKIP_SANDBOX,
7, //todo: change it back to 1
1, //todo: change it back to 1
conditionNodes,
0,
"",
Expand All @@ -101,14 +112,20 @@ contract MachineStateManager {
));
currentMachineState.afterOpPlugins.push(Plugin(
EnumReturnType.NO,
7, // todo: change it back to 1
1, // todo: change it back to 1
conditionNodes,
0,
"",
true,
true,
false
));

// set dividend permyriad per transaction as 500
currentMachineState.machineStateParameters.dividendPermyriadPerTransaction = 500;

// set the dividend cycle of transactions as 1
currentMachineState.machineStateParameters.dividendCycleOfTransactions = 1;
}

/**
Expand Down Expand Up @@ -236,5 +253,182 @@ contract MachineStateManager {
}

}



/**
* This function that get the total number of tokens for a certain token class
* @param bIsSandbox The flag to indicate whether is the sandbox
* @param tokenClassIndex The index of the token class
*/
function totalTokensPerTokenClass(bool bIsSandbox, uint256 tokenClassIndex) internal view returns (uint256) {
if (bIsSandbox) {
uint256 numberOfOwners = sandboxMachineState.tokenList[tokenClassIndex].ownerList.length;
uint256 totalTokens = 0;
bool bIsValid = true;
for (uint256 i = 0; i < numberOfOwners; i++) {
address currentOwner = sandboxMachineState.tokenList[tokenClassIndex].ownerList[i];
uint256 currentNumberOfTokens = sandboxMachineState.tokenList[tokenClassIndex].tokenBalance[currentOwner];
(bIsValid, totalTokens) = SafeMathUpgradeable.tryAdd(totalTokens, currentNumberOfTokens);
require(bIsValid, "totalTokensPerTokenClass: totalTokens overflow");
}
return totalTokens;
} else {
uint256 numberOfOwners = currentMachineState.tokenList[tokenClassIndex].ownerList.length;
uint256 totalTokens = 0;
bool bIsValid = true;
for (uint256 i = 0; i < numberOfOwners; i++) {
address currentOwner = currentMachineState.tokenList[tokenClassIndex].ownerList[i];
uint256 currentNumberOfTokens = currentMachineState.tokenList[tokenClassIndex].tokenBalance[currentOwner];
(bIsValid, totalTokens) = SafeMathUpgradeable.tryAdd(totalTokens, currentNumberOfTokens);
require(bIsValid, "totalTokensPerTokenClass: totalTokens overflow");
}
return totalTokens;
}
}

/**
* Return the number of dividend weight for a certain token class
* @param bIsSandbox Whether is the sandbox
* @param tokenClassIndex The index of the token class
*/
function sumDividendWeightForTokenClass( bool bIsSandbox, uint256 tokenClassIndex ) internal view returns (uint256) {
if (bIsSandbox) {
uint256 dividendWeightUnit = sandboxMachineState.tokenList[tokenClassIndex].dividendWeight;
bool bIsValid = true;
uint256 dividendWeight = 0;
(bIsValid, dividendWeight) = SafeMathUpgradeable.tryMul(dividendWeightUnit, totalTokensPerTokenClass(bIsSandbox, tokenClassIndex));
require(bIsValid, "sumDividendWeightForTokenClass: dividendWeight overflow");
return dividendWeight;
} else {
uint256 dividendWeightUnit = currentMachineState.tokenList[tokenClassIndex].dividendWeight;
bool bIsValid = true;
uint256 dividendWeight = 0;
(bIsValid, dividendWeight) = SafeMathUpgradeable.tryMul(dividendWeightUnit, totalTokensPerTokenClass(bIsSandbox, tokenClassIndex));
require(bIsValid, "sumDividendWeightForTokenClass: dividendWeight overflow");
return dividendWeight;
}
}

/**
* Return the number of voting weight for a certain token class
* @param bIsSandbox Whether is the sandbox
* @param tokenClassIndex The index of the token class
*/
function sumVotingWeightForTokenClass ( bool bIsSandbox, uint256 tokenClassIndex ) internal view returns (uint256) {
if (bIsSandbox) {
uint256 votingWeightUnit = sandboxMachineState.tokenList[tokenClassIndex].votingWeight;
bool bIsValid = true;
uint256 votingWeight = 0;
(bIsValid, votingWeight) = SafeMathUpgradeable.tryMul(votingWeightUnit, totalTokensPerTokenClass(bIsSandbox, tokenClassIndex));
require(bIsValid, "sumVotingWeightForTokenClass: votingWeight overflow");
return votingWeight;
} else {
uint256 votingWeightUnit = currentMachineState.tokenList[tokenClassIndex].votingWeight;
bool bIsValid = true;
uint256 votingWeight = 0;
(bIsValid, votingWeight) = SafeMathUpgradeable.tryMul(votingWeightUnit, totalTokensPerTokenClass(bIsSandbox, tokenClassIndex));
require(bIsValid, "sumVotingWeightForTokenClass: votingWeight overflow");
return votingWeight;
}
}

/**
* Calculate the current dividend per unit
* @param bIsSandbox The flag to indicate whether is the sandbox
*/

function currentDividendPerUnit(bool bIsSandbox) public view returns(uint256) {
if (bIsSandbox) {
// make sure that the dividend per myriad per transaction is less than 1000
require(sandboxMachineState.machineStateParameters.dividendPermyriadPerTransaction < 1000,
ErrorMsg.By(15));

// make sure that cycle counter is less than the threashold
require(sandboxMachineState.machineStateParameters.dividendCycleCounter >=
sandboxMachineState.machineStateParameters.dividendCycleOfTransactions, ErrorMsg.By(16));

// 1. calculate the total amount of dividends to be offered
bool bIsValid = true;
uint256 totalDividends = 0;

(bIsValid, totalDividends) = SafeMathUpgradeable.tryMul(
sandboxMachineState.machineStateParameters.currentCashBalanceForDividends,
sandboxMachineState.machineStateParameters.dividendPermyriadPerTransaction);

(bIsValid, totalDividends) = SafeMathUpgradeable.tryDiv(
totalDividends,
1000);
require (bIsValid, ErrorMsg.By(12));

// 2. calculate the total dividends weight of all dividendable tokens
uint256 totalDividendsWeight = 0;

for (uint256 index=0; index < sandboxMachineState.tokenList.length; index++) {

if (sandboxMachineState.tokenList[index].bIsInitialized == false) {
break;
}

(bIsValid, totalDividendsWeight) = SafeMathUpgradeable.tryAdd(
totalDividendsWeight,
sumDividendWeightForTokenClass(bIsSandbox, index));
require(bIsValid, ErrorMsg.By(12));
}

// 3. calculate the cash dividend per unit
uint256 cashPerUnit = 0;
(bIsValid, cashPerUnit) = SafeMathUpgradeable.tryDiv(
totalDividends,
totalDividendsWeight);

return (cashPerUnit);
} else {
// make sure that the dividend per myriad per transaction is less than 1000
require(currentMachineState.machineStateParameters.dividendPermyriadPerTransaction < 1000,
ErrorMsg.By(15));

// make sure that cycle counter is less than the threashold
require(currentMachineState.machineStateParameters.dividendCycleCounter >=
currentMachineState.machineStateParameters.dividendCycleOfTransactions, ErrorMsg.By(16));

// 1. calculate the total amount of dividends to be offered
bool bIsValid = true;
uint256 totalDividends = 0;

(bIsValid, totalDividends) = SafeMathUpgradeable.tryMul(
currentMachineState.machineStateParameters.currentCashBalanceForDividends,
currentMachineState.machineStateParameters.dividendPermyriadPerTransaction);

(bIsValid, totalDividends) = SafeMathUpgradeable.tryDiv(
totalDividends,
1000);
require (bIsValid, ErrorMsg.By(12));

// 2. calculate the total dividends weight of all dividendable tokens
uint256 totalDividendsWeight = 0;

for (uint256 index=0; index < currentMachineState.tokenList.length; index++) {

if (currentMachineState.tokenList[index].bIsInitialized == false) {
break;
}

(bIsValid, totalDividendsWeight) = SafeMathUpgradeable.tryAdd(
totalDividendsWeight,
sumDividendWeightForTokenClass(bIsSandbox, index));
require(bIsValid, ErrorMsg.By(12));
}

// 3. calculate the cash dividend per unit
uint256 cashPerUnit = 0;
(bIsValid, cashPerUnit) = SafeMathUpgradeable.tryDiv(
totalDividends,
totalDividendsWeight);

return (cashPerUnit);
}
}



}
4 changes: 2 additions & 2 deletions darc-protocol/contracts/Opcodes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ enum EnumOpcode {

/**
* @notice Call emergency agents to handle emergency situations
* @param uint256[] addressArray: the array of the emergency agent index to call
* @param UINT256_2DARRAY[0] address[] addressArray: the array of the emergency agents index to call
* ID:24
*/
CALL_EMERGENCY,
Expand Down Expand Up @@ -276,7 +276,7 @@ enum EnumOpcode {

/**
* @notice Add storage IPFS hash to the storage list permanently
* @paran address: the address to set approval for all cash withdraw operations
* @paran STRING_2DARRAY[0] address: the address to set approval for all cash withdraw operations
* ID:31
*/
ADD_STORAGE_IPFS_HASH,
Expand Down
2 changes: 1 addition & 1 deletion darc-protocol/contracts/Program.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ enum EnumParameterType {

enum MachineParameter{
UNDEFINED,
dividentPermyriadPerTransaction,
dividendPermyriadPerTransaction,
dividendCycleOfTransactions,
currentCashBalanceForDividends,
dividendCycleCounter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import "./Instructions/PluginInstructions.sol";
import "./Instructions/ParameterInstructions.sol";
import "./Instructions/MoneyInstructions.sol";
import "./Instructions/UtilityInstructions.sol";
import "./Instructions/OfferDividendsInstructions.sol";

/**
* @title Instruction Machine, the executor of the DARC Program instructions on the DARC Machine State
Expand All @@ -29,7 +30,8 @@ MembershipInstructions,
PluginInstructions,
ParameterInstructions,
MoneyInstructions,
UtilityInstructions
UtilityInstructions,
OfferDividendsInstructions
{

/**
Expand Down Expand Up @@ -86,6 +88,9 @@ UtilityInstructions
else if (operation.opcode == EnumOpcode.PAY_CASH) {
op_PAY_CASH(operation, bIsSandbox);
}
else if (operation.opcode == EnumOpcode.OFFER_DIVIDENDS) {
op_OFFER_DIVIDENDS(operation, bIsSandbox);
}
else if (operation.opcode == EnumOpcode.BATCH_PAY_TO_MINT_TOKENS){
op_BATCH_PAY_TO_MINT_TOKENS(operation, bIsSandbox);
}
Expand Down
Loading

0 comments on commit 0657011

Please sign in to comment.