Skip to content

Commit

Permalink
Merge pull request #350 from Thetta/dev-enkogu-sept
Browse files Browse the repository at this point in the history
#341: ppm
  • Loading branch information
AnthonyAkentiev authored Oct 5, 2018
2 parents ed54c59 + 20231c0 commit 59c1b05
Show file tree
Hide file tree
Showing 14 changed files with 392 additions and 381 deletions.
8 changes: 4 additions & 4 deletions contracts/moneyflow/IReceiver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ pragma solidity ^0.4.23;
*/
contract IReceiver {
// In case we have absolute output -> will return 0
// in 1/100th percents of input. Examples:
// 12 is 0.12% of input;
// 100 is 1% of input
function getPercentsMul100() public view returns(uint);
// in 1/10000th percents of input. Examples:
// 1200 is 0.12% of input;
// 10000 is 1% of input
function getPartsPerMillion() public view returns(uint);

// If this output needs more funds -> will return true
// If this output does not need more funds -> will return false
Expand Down
75 changes: 44 additions & 31 deletions contracts/moneyflow/MoneflowTable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "zeppelin-solidity/contracts/math/SafeMath.sol";
import "zeppelin-solidity/contracts/ownership/Ownable.sol";


contract MoneyflowTable is Ownable {//is IWeiReceiver,
contract MoneyflowTable is IWeiReceiver, Ownable {
uint public elementsCount = 0;
enum ElementTypes {
AbsoluteExpense,
Expand All @@ -26,7 +26,7 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,

struct Expense {
uint neededAmount;
uint neededPercentsMul100;
uint neededPpm;

uint periodHours;

Expand All @@ -47,14 +47,18 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,

// -------------------- INTERNAL IWEIRECEIVER FUNCTIONS -------------------- for elements

function _getPercentsMul100(uint _eId) internal view returns(uint) {
function _getPartsPerMillion(uint _eId) internal view returns(uint) {
if(ElementTypes.RelativeExpense == elementsType[_eId]) {
return expenses[_eId].neededPercentsMul100;
return expenses[_eId].neededPpm;
}else {
return 0;
}
}

function isElementNeedsMoney(uint _id)view external returns(bool) {
return _isNeedsMoney(_id);
}

function _isNeedsMoney(uint _eId) internal view returns(bool) {
if(splitters[_eId].isOpen) {
return _isNeedsMoneySplitter(_eId);
Expand Down Expand Up @@ -139,28 +143,28 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,

function _getMinWeiNeededUnsortedSplitter(uint _eId) internal view returns(uint) {
uint absSum = 0;
uint percentsMul100ReverseSum = 10000;
uint partsPerMillionReverseSum = 1000000;

for(uint i=0; i<splitters[_eId].outputs.length; ++i) {
if(ElementTypes.RelativeExpense == elementsType[splitters[_eId].outputs[i]]) {
percentsMul100ReverseSum -= expenses[splitters[_eId].outputs[i]].neededPercentsMul100;
partsPerMillionReverseSum -= expenses[splitters[_eId].outputs[i]].neededPpm;
}else {
absSum += _getMinWeiNeeded(splitters[_eId].outputs[i]);
}
}

if(percentsMul100ReverseSum==0) {
if(partsPerMillionReverseSum==0) {
return 0;
}else {
return 10000*absSum/percentsMul100ReverseSum;
return 1000000*absSum/partsPerMillionReverseSum;
}
}

function _getMinWeiNeededTopdownSplitter(uint _eId) internal view returns(uint) {
uint out = 0;
for(uint j=splitters[_eId].outputs.length; j>0; --j) {
if(ElementTypes.RelativeExpense == elementsType[splitters[_eId].outputs[j-1]]) {
out = 10000 * out / expenses[splitters[_eId].outputs[j-1]].neededPercentsMul100;
out = 1000000 * out / expenses[splitters[_eId].outputs[j-1]].neededPpm;
}else {
out += _getMinWeiNeeded(splitters[_eId].outputs[j-1]);
}
Expand Down Expand Up @@ -221,40 +225,45 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,
}

if(ElementTypes.RelativeExpense==elementsType[_eId]) {
return (_getDebtMultiplier(_eId)*(expenses[_eId].neededPercentsMul100 * _currentFlow)) / 10000;
return (_getDebtMultiplier(_eId)*(expenses[_eId].neededPpm * _currentFlow)) / 1000000;
}else {
return _getMinWeiNeeded(_eId);
}
}

function getElementBalance(uint _eId)external view returns(uint) {
function getElementBalance(uint _eId)public view returns(uint) {
return expenses[_eId].balance;
}

// -------------------- EXTERNAL IWEIRECEIVER FUNCTIONS -------------------- for all table
// -------------------- public IWEIRECEIVER FUNCTIONS -------------------- for all table

function isNeedsMoney()view external returns(bool) {
function isNeedsMoney()view public returns(bool) {
return _isNeedsMoney(0);
}

function processFunds(uint _currentFlow) external payable {
function getPartsPerMillion() public view returns(uint) {
return _getPartsPerMillion(0);
}

function processFunds(uint _currentFlow) public payable {
require(_currentFlow>=_getMinWeiNeeded(0));
require(msg.value>=_getMinWeiNeeded(0));


return _processFunds(0, _currentFlow, msg.value);
}

function getMinWeiNeeded()external view returns(uint) {
function getMinWeiNeeded()public view returns(uint) {
return _getMinWeiNeeded(0);
}

function getTotalWeiNeeded(uint _currentFlow)external view returns(uint) {
function getTotalWeiNeeded(uint _currentFlow)public view returns(uint) {
return _getTotalWeiNeeded(0, _currentFlow);
}

// -------------------- EXTERNAL SCHEME FUNCTIONS --------------------
// -------------------- public SCHEME FUNCTIONS --------------------

function addAbsoluteExpense(uint _neededAmount, bool _isPeriodic, bool _isAccumulateDebt, uint _periodHours, IWeiReceiver _output)external onlyOwner {
function addAbsoluteExpense(uint _neededAmount, bool _isPeriodic, bool _isAccumulateDebt, uint _periodHours, IWeiReceiver _output)public onlyOwner returns(uint) {
expenses[elementsCount] = Expense(
_neededAmount, 0,
_periodHours, _isPeriodic, _isAccumulateDebt, _output,
Expand All @@ -263,41 +272,45 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,
elementsType[elementsCount] = ElementTypes.AbsoluteExpense;
emit ElementAdded(elementsCount, ElementTypes.AbsoluteExpense);
elementsCount += 1;
return elementsCount-1;
}

function addRelativeExpense(uint _neededPercentsMul100, bool _isPeriodic, bool _isAccumulateDebt, uint _periodHours, IWeiReceiver _output)external onlyOwner {
function addRelativeExpense(uint _neededPpm, bool _isPeriodic, bool _isAccumulateDebt, uint _periodHours, IWeiReceiver _output)public onlyOwner returns(uint) {
expenses[elementsCount] = Expense(
0, _neededPercentsMul100,
0, _neededPpm,
_periodHours, _isPeriodic, _isAccumulateDebt, _output,
0, false, true, 0
);
elementsType[elementsCount] = ElementTypes.RelativeExpense;
emit ElementAdded(elementsCount, ElementTypes.RelativeExpense);
elementsCount += 1;
return elementsCount-1;
}

function addTopdownSplitter()external onlyOwner {
function addTopdownSplitter()public onlyOwner returns(uint) {
uint[] memory emptyOutputs;
splitters[elementsCount] = Splitter(true, emptyOutputs);
elementsType[elementsCount] = ElementTypes.TopdownSplitter;
emit ElementAdded(elementsCount, ElementTypes.TopdownSplitter);
elementsCount += 1;
return elementsCount-1;
}

function addUnsortedSplitter()external onlyOwner {
function addUnsortedSplitter()public onlyOwner returns(uint) {
uint[] memory emptyOutputs;
splitters[elementsCount] = Splitter(true, emptyOutputs);
elementsType[elementsCount] = ElementTypes.UnsortedSplitter;
emit ElementAdded(elementsCount, ElementTypes.UnsortedSplitter);
elementsCount += 1;
return elementsCount-1;
}

function addChild(uint _splitterId, uint _childId)external onlyOwner {
function addChild(uint _splitterId, uint _childId)public onlyOwner returns(uint) {
// add require`s
splitters[_splitterId].outputs.push(_childId);
}

// -------------------- EXTERNAL CONTROL FUNCTIONS --------------------
// -------------------- public CONTROL FUNCTIONS --------------------


function _isExpense(uint _eId) internal returns(bool) {
Expand All @@ -318,7 +331,7 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,
}
}

function openElement(uint _eId) external onlyOwner {
function openElement(uint _eId) public onlyOwner {
if(_isExpense(_eId)) {
expenses[_eId].isOpen = true;

Expand All @@ -330,7 +343,7 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,
}
}

function closeElement(uint _eId)external onlyOwner {
function closeElement(uint _eId)public onlyOwner {
if(_isExpense(_eId)) {
expenses[_eId].isOpen = false;

Expand All @@ -342,7 +355,7 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,
}
}

function isOpen(uint _eId) external view returns(bool) {
function isOpen(uint _eId) public view returns(bool) {
if(_isExpense(_eId)) {
return expenses[_eId].isOpen;

Expand All @@ -355,23 +368,23 @@ contract MoneyflowTable is Ownable {//is IWeiReceiver,

}

function getChildrenCount(uint _eId)external view returns(uint) {
function getChildrenCount(uint _eId)public view returns(uint) {
require(_isSplitter(_eId));
return splitters[_eId].outputs.length;
}

function getChildId(uint _eId, uint _index)external view returns(uint) {
function getChildId(uint _eId, uint _index)public view returns(uint) {
require(_isSplitter(_eId));
require(splitters[_eId].outputs.length>_index);
return splitters[_eId].outputs[_index];
}

function withdrawFundsFromElement(uint _eId)external onlyOwner {
function withdrawFundsFromElement(uint _eId)public onlyOwner {
// require(_isExpense(_eId));
expenses[_eId].output.processFunds.value(expenses[_eId].balance)(expenses[_eId].balance);
expenses[_eId].balance = 0;
}

function() external {
function() public {
}
}
2 changes: 1 addition & 1 deletion contracts/moneyflow/Moneyflow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ contract MoneyFlow is IMoneyflow, DaoClient, Ownable {
DaoClient(_daoBase)
{
// do not set output!
donationEndpoint = new WeiRelativeExpenseWithPeriod(10000, 0, false);
donationEndpoint = new WeiRelativeExpenseWithPeriod(1000000, 0, false);
donationF2WR = new FallbackToWeiReceiver(donationEndpoint);
}

Expand Down
28 changes: 14 additions & 14 deletions contracts/moneyflow/ether/WeiExpense.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,27 @@ contract WeiExpense is IWeiReceiver, IDestination, Ownable {
bool isMoneyReceived = false;
bool isAccumulateDebt = false;
bool isPeriodic = false;
uint percentsMul100 = 0;
uint partsPerMillion = 0;
uint periodHours = 0;
uint momentReceived = 0;
uint neededWei = 0;
address moneySource = 0x0;

event WeiExpenseFlush(address _owner, uint _balance);
event WeiExpenseSetNeededWei(uint _neededWei);
event WeiExpenseSetPercents(uint _percentsMul100);
event WeiExpenseSetPercents(uint _partsPerMillion);
event WeiExpenseProcessFunds(address _sender, uint _value, uint _currentFlow);

/**
* @dev Constructor
* @param _neededWei - absolute value. how much Ether this expense should receive (in Wei). Can be zero (use _percentsMul100 in this case)
* @param _percentsMul100 - if need to get % out of the input flow -> specify this parameter (1% is 100 units)
* @param _neededWei - absolute value. how much Ether this expense should receive (in Wei). Can be zero (use _partsPerMillion in this case)
* @param _partsPerMillion - if need to get % out of the input flow -> specify this parameter (1% is 10000 units)
* @param _periodHours - if not isPeriodic and periodHours>0 ->no sense. if isPeriodic and periodHours==0 -> needs money everytime. if isPeriodic and periodHours>0 -> needs money every period.
* @param _isAccumulateDebt - if you don't pay in the current period -> will accumulate the needed amount (only for _neededWei!)
* @param _isPeriodic - if isPeriodic and periodHours>0 -> needs money every period. if isPeriodic and periodHours==0 -> needs money everytime.
*/
constructor(uint _neededWei, uint _percentsMul100, uint _periodHours, bool _isAccumulateDebt, bool _isPeriodic) public {
percentsMul100 = _percentsMul100;
constructor(uint _neededWei, uint _partsPerMillion, uint _periodHours, bool _isAccumulateDebt, bool _isPeriodic) public {
partsPerMillion = _partsPerMillion;
periodHours = _periodHours;
neededWei = _neededWei;
isAccumulateDebt = _isAccumulateDebt;
Expand Down Expand Up @@ -71,15 +71,15 @@ contract WeiExpense is IWeiReceiver, IDestination, Ownable {
return 0;
}

if(0!=percentsMul100) {
return (getDebtMultiplier()*(percentsMul100 * _inputWei)) / 10000;
if(0!=partsPerMillion) {
return (getDebtMultiplier()*(partsPerMillion * _inputWei)) / 1000000;
}else {
return getMinWeiNeeded();
}
}

function getMinWeiNeeded()public view returns(uint) {
if(!isNeedsMoney() || (0!=percentsMul100)) {
if(!isNeedsMoney() || (0!=partsPerMillion)) {
return 0;
}
return getDebtMultiplier()*neededWei;
Expand Down Expand Up @@ -112,8 +112,8 @@ contract WeiExpense is IWeiReceiver, IDestination, Ownable {
_;
}

function getPercentsMul100()public view returns(uint) {
return percentsMul100;
function getPartsPerMillion()public view returns(uint) {
return partsPerMillion;
}

function flush()public onlyOwner {
Expand All @@ -131,9 +131,9 @@ contract WeiExpense is IWeiReceiver, IDestination, Ownable {
neededWei = _neededWei;
}

function setPercents(uint _percentsMul100) public onlyOwner {
emit WeiExpenseSetPercents(_percentsMul100);
percentsMul100 = _percentsMul100;
function setPercents(uint _partsPerMillion) public onlyOwner {
emit WeiExpenseSetPercents(_partsPerMillion);
partsPerMillion = _partsPerMillion;
}

function()public {
Expand Down
4 changes: 2 additions & 2 deletions contracts/moneyflow/ether/WeiFund.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import "zeppelin-solidity/contracts/ownership/Ownable.sol";
*/


contract WeiFund is IWeiReceiver, IDestination, Ownable {//
contract WeiFund is IWeiReceiver, IDestination, Ownable {
using SafeMath for uint;

uint neededWei;
Expand Down Expand Up @@ -89,7 +89,7 @@ contract WeiFund is IWeiReceiver, IDestination, Ownable {//
return 0;
}

function getPercentsMul100() view public returns(uint) {
function getPartsPerMillion() view public returns(uint) {
return 0;
}

Expand Down
4 changes: 2 additions & 2 deletions contracts/moneyflow/ether/WeiRelativeExpense.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "./WeiExpense.sol";


contract WeiRelativeExpense is WeiExpense {
constructor(uint _percentsMul100)public
WeiExpense(0, _percentsMul100, 0, false, false)
constructor(uint _partsPerMillion)public
WeiExpense(0, _partsPerMillion, 0, false, false)
{}
}
4 changes: 2 additions & 2 deletions contracts/moneyflow/ether/WeiRelativeExpenseWithPeriod.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "./WeiExpense.sol";


contract WeiRelativeExpenseWithPeriod is WeiExpense {
constructor(uint _percentsMul100, uint _periodHours, bool _isAccumulateDebt) public
WeiExpense(0, _percentsMul100, _periodHours, _isAccumulateDebt, true)
constructor(uint _partsPerMillion, uint _periodHours, bool _isAccumulateDebt) public
WeiExpense(0, _partsPerMillion, _periodHours, _isAccumulateDebt, true)
{}
}
Loading

0 comments on commit 59c1b05

Please sign in to comment.