Skip to content
This repository was archived by the owner on Jun 15, 2021. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ lib-cov

# Coverage directory used by tools like istanbul
coverage
coverage.json

# nyc test coverage
.nyc_output
Expand Down Expand Up @@ -62,10 +63,11 @@ typings/

# zos sessions
zos.dev-*
.zos.session
.openzeppelin/.session
.openzeppelin/dev-*

# contracts build
build

.zos.session

.DS_Store
14 changes: 7 additions & 7 deletions zos.json → .openzeppelin/project.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"zosversion": "2.2",
"manifestVersion": "2.2",
"contracts": {
"StaticCurveLogic": "StaticCurveLogic",
"BancorCurveLogic": "BancorCurveLogic",
Expand All @@ -10,15 +10,15 @@
"BancorCurveService": "BancorCurveService"
},
"dependencies": {
"openzeppelin-eth": "^2.2.0"
"@openzeppelin/contracts-ethereum-package": "^2.2.3"
},
"name": "bc-dao",
"version": "0.0.1",
"name": "@dorg/bc-dao",
"version": "0.0.1-alpha",
"compiler": {
"manager": "zos",
"manager": "openzeppelin",
"solcVersion": "0.5.10",
"compilerSettings": {
"optimizer": {}
},
"solcVersion": "0.5.10"
}
}
}
8 changes: 8 additions & 0 deletions .solcover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
norpc: false,
skipFiles: [
"BondingCurve/curve/bancor-formula/BancorFormula.sol",
"BondingCurve/curve/bancor-formula/Power.sol"
],
copyPackages: ["openzeppelin-test-helpers"]
};
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function sell(
) public
```

[**`pay`**](./contracts/BondingCurve/BondingCurve.sol): Pay the DAO in collateralTokens. Revenue send in this method is distributed between the beneficiary and the bondedToken holders according to the splitOnPay parameter;
[**`pay`**](./contracts/BondingCurve/BondingCurve.sol): Pay the DAO in collateralTokens. Revenue sent using this method is distributed between the beneficiary and the bondedToken holders according to the splitOnPay parameter;

```
function pay(
Expand Down Expand Up @@ -202,4 +202,4 @@ We envision the following features may be useful to DAOs implementing bonding cu

### Technical Features

- **Modularity** - We envision an "OpenZeppelin for bonding curves" - an open source repo to compose your own bonding curve from a suite of well-established components.
- **Modularity** - We envision an "OpenZeppelin for bonding curves" - an open source repo to compose your own bonding curve from a suite of well-established components.
110 changes: 70 additions & 40 deletions contracts/BondingCurve/BondingCurve.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
pragma solidity ^0.5.7;

import "openzeppelin-eth/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-eth/contracts/math/SafeMath.sol";
import "openzeppelin-eth/contracts/ownership/Ownable.sol";
import "zos-lib/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "./interface/ICurveLogic.sol";
import "./dividend/DividendPool.sol";
import "./token/BondedToken.sol";
Expand Down Expand Up @@ -42,13 +42,28 @@ contract BondingCurve is Initializable, Ownable {
string internal constant NO_MICRO_PAYMENTS = "Payment amount must be greater than 100 'units' for calculations to work correctly";
string internal constant TOKEN_BURN_FAILED = "bondedToken burn failed";
string internal constant TRANSFER_TO_RECIPIENT_FAILED = "Transfer to recipient failed";


event BeneficiarySet(address beneficiary);

event Buy(address indexed buyer, address indexed recipient, uint256 amount, uint256 price, uint256 reserveAmount, uint256 beneficiaryAmount);
event BuyCurveSet(address buyCurve);
event SellCurveSet(address sellCurve);
event SplitOnPaySet(uint256 splitOnPay);

event Buy(
address indexed buyer,
address indexed recipient,
uint256 amount,
uint256 price,
uint256 reserveAmount,
uint256 beneficiaryAmount
);
event Sell(address indexed seller, address indexed recipient, uint256 amount, uint256 reward);
event Pay(address indexed from, address indexed token, uint256 amount, uint256 beneficiaryAmount, uint256 dividendAmount);
event Pay(
address indexed from,
address indexed token,
uint256 amount,
uint256 beneficiaryAmount,
uint256 dividendAmount
);

/// @dev Initialize contract
/// @param owner Contract owner, can conduct administrative functions.
Expand All @@ -69,7 +84,7 @@ contract BondingCurve is Initializable, Ownable {
DividendPool dividendPool,
uint256 splitOnPay
) public initializer {
require(splitOnPay >= 0 && splitOnPay <= MAX_PERCENTAGE, SPLIT_ON_PAY_INVALID);
require(splitOnPay <= 100, SPLIT_ON_PAY_INVALID);

Ownable.initialize(owner);

Expand All @@ -83,6 +98,12 @@ contract BondingCurve is Initializable, Ownable {
_dividendPool = dividendPool;

_splitOnPay = splitOnPay;

emit BuyCurveSet(address(_buyCurve));
emit SellCurveSet(address(_sellCurve));
emit SplitOnPaySet(_splitOnPay);
emit SplitOnPaySet(splitOnPay);

}

/// @notice Get the price in ether to mint tokens
Expand All @@ -101,8 +122,7 @@ contract BondingCurve is Initializable, Ownable {
/// @param numTokens The number of bondedTokens to buy
/// @param maxPrice Maximum total price allowable to pay in collateralTokens. If zero, any price is allowed.
/// @param recipient Address to send the new bondedTokens to
function buy(uint256 numTokens, uint256 maxPrice, address recipient)
public {
function buy(uint256 numTokens, uint256 maxPrice, address recipient) public {
require(numTokens > 0, REQUIRE_NON_ZERO_NUM_TOKENS);

uint256 buyPrice = priceToBuy(numTokens);
Expand All @@ -120,17 +140,13 @@ contract BondingCurve is Initializable, Ownable {

_reserveBalance = _reserveBalance.add(tokensToReserve);

require(_bondedToken.mint(recipient, numTokens), TOKEN_MINTING_FAILED);
_bondedToken.mint(recipient, numTokens);

require(
_collateralToken.transferFrom(msg.sender, address(this), buyPrice),
TRANSFER_FROM_FAILED
);

require(
_collateralToken.transfer(_beneficiary, tokensToBeneficiary),
TRANSFER_TO_BENEFICIARY_FAILED
);
_collateralToken.transfer(_beneficiary, tokensToBeneficiary);

emit Buy(msg.sender, recipient, numTokens, buyPrice, tokensToReserve, tokensToBeneficiary);
}
Expand All @@ -139,9 +155,7 @@ contract BondingCurve is Initializable, Ownable {
/// @param numTokens The number of bondedTokens to sell
/// @param minPrice Minimum total price allowable to receive in collateralTokens
/// @param recipient Address to send collateralTokens to
function sell(uint256 numTokens, uint256 minPrice, address recipient)
public {

function sell(uint256 numTokens, uint256 minPrice, address recipient) public {
require(numTokens > 0, REQUIRE_NON_ZERO_NUM_TOKENS);
require(_bondedToken.balanceOf(msg.sender) >= numTokens, INSUFFICENT_TOKENS);

Expand All @@ -151,7 +165,7 @@ contract BondingCurve is Initializable, Ownable {
_reserveBalance = _reserveBalance.sub(burnReward);

_bondedToken.burn(msg.sender, numTokens);
require(_collateralToken.transfer(recipient, burnReward), TRANSFER_TO_RECIPIENT_FAILED);
_collateralToken.transfer(recipient, burnReward);

emit Sell(msg.sender, recipient, numTokens, burnReward);
}
Expand All @@ -162,35 +176,30 @@ contract BondingCurve is Initializable, Ownable {
function pay(uint256 amount) public {
require(amount > MICRO_PAYMENT_THRESHOLD, NO_MICRO_PAYMENTS);

//TODO: Get payment token from dividendPool
IERC20 paymentToken = _collateralToken;

uint256 tokensToBeneficiary;
uint256 tokensToDividendHolders;
uint256 remainderTokens;

// Calculate amounts to beneficiary and dividend holders based on splitOnPay
if (_splitOnPay == 0) {
tokensToDividendHolders = amount;
} else if (_splitOnPay == MAX_PERCENTAGE) {
tokensToBeneficiary = amount;
} else {
uint256 dividendPercentage = MAX_PERCENTAGE.sub(_splitOnPay);

tokensToBeneficiary = (amount.mul(_splitOnPay)).div(MAX_PERCENTAGE);
tokensToDividendHolders = (amount.mul(dividendPercentage)).div(MAX_PERCENTAGE);
}

// require(tokensToBeneficiary.add(tokensToDividendHolders) <= amount, SPLIT_ON_PAY_MATH_ERROR);
uint256 dividendPercentage = MAX_PERCENTAGE.sub(_splitOnPay);

// uint256 remainderTokens = amount.sub(tokensToBeneficiary).sub(tokensToDividendHolders);
tokensToBeneficiary = (amount.mul(_splitOnPay)).div(MAX_PERCENTAGE);
tokensToDividendHolders = (amount.mul(dividendPercentage)).div(MAX_PERCENTAGE);
remainderTokens = amount.sub(tokensToBeneficiary).sub(tokensToDividendHolders);

require(paymentToken.transferFrom(msg.sender, address(this), amount), TRANSFER_FROM_FAILED);

require(paymentToken.transfer(_beneficiary, tokensToBeneficiary), "Transfer to beneficiary failed");
require(paymentToken.transfer(address(_dividendPool), tokensToDividendHolders), "Transfer to dividend pool failed");
// require(paymentToken.transfer(msg.sender, remainderTokens), "Transfer of remainder to sender failed");
paymentToken.transfer(_beneficiary, tokensToBeneficiary);
paymentToken.transfer(address(_dividendPool), tokensToDividendHolders.add(remainderTokens));

emit Pay(msg.sender, address(paymentToken), amount, tokensToBeneficiary, tokensToDividendHolders);
emit Pay(
msg.sender,
address(paymentToken),
amount,
tokensToBeneficiary,
tokensToDividendHolders
);
}

/*
Expand All @@ -204,6 +213,27 @@ contract BondingCurve is Initializable, Ownable {
emit BeneficiarySet(_beneficiary);
}

/// @notice Set buy curve to a new address
/// @param buyCurve New buy curve
function setBuyCurve(ICurveLogic buyCurve) public onlyOwner {
_buyCurve = buyCurve;
emit BuyCurveSet(address(_buyCurve));
}

/// @notice Set sell curve to a new address
/// @param sellCurve New sell curve
function setSellCurve(ICurveLogic sellCurve) public onlyOwner {
_sellCurve = sellCurve;
emit SellCurveSet(address(_sellCurve));
}

/// @notice Set split on pay to new value
/// @param splitOnPay New split on pay value
function setSplitOnPay(uint256 splitOnPay) public onlyOwner {
_splitOnPay = splitOnPay;
emit SplitOnPaySet(_splitOnPay);
}

/*
Getter Functions
*/
Expand Down
Binary file removed contracts/BondingCurve/curve/.DS_Store
Binary file not shown.
9 changes: 7 additions & 2 deletions contracts/BondingCurve/curve/BancorCurveLogic.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity >= 0.4.22 <6.0.0;

import "openzeppelin-eth/contracts/math/SafeMath.sol";
import "zos-lib/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "../interface/ICurveLogic.sol";
import "./BancorCurveService.sol";

Expand Down Expand Up @@ -61,4 +61,9 @@ contract BancorCurveLogic is Initializable, ICurveLogic {
function reserveRatio() public view returns (uint32) {
return _reserveRatio;
}

/// @notice Get bancor service address
function bancorService() public view returns (BancorCurveService) {
return _bancorService;
}
}
4 changes: 2 additions & 2 deletions contracts/BondingCurve/curve/BancorCurveService.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity ^0.5.7;

import "openzeppelin-eth/contracts/math/SafeMath.sol";
import "zos-lib/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "./bancor-formula/BancorFormula.sol";

/**
Expand Down
10 changes: 5 additions & 5 deletions contracts/BondingCurve/curve/StaticCurveLogic.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity >= 0.4.22 <6.0.0;
pragma solidity ^0.5.7;

import "zos-lib/contracts/Initializable.sol";
import "openzeppelin-eth/contracts/math/SafeMath.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import "../interface/ICurveLogic.sol";

/**
Expand All @@ -21,7 +21,7 @@ contract StaticCurveLogic is Initializable, ICurveLogic {

/// @dev Initialize contract
/// @param tokenRatio Ratio of reserve tokens transfered or recieved to bonded tokens minted or burned, respectively. Divided by precison value for calculations.
function initialize(uint256 tokenRatio) public initializer {
function initialize(uint256 tokenRatio) initializer public {
_tokenRatio = tokenRatio;
}

Expand Down Expand Up @@ -49,7 +49,7 @@ contract StaticCurveLogic is Initializable, ICurveLogic {
}

/// @notice Get token ratio
function tokenRatio() public view returns (uint256) {
function tokenRatio() public returns (uint256) {
return _tokenRatio;
}

Expand Down
4 changes: 2 additions & 2 deletions contracts/BondingCurve/curve/bancor-formula/BancorFormula.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity >= 0.4.22 <6.0.0;

import "openzeppelin-eth/contracts/math/SafeMath.sol";
import "zos-lib/contracts/Initializable.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import "./Power.sol";

/**
Expand Down
2 changes: 1 addition & 1 deletion contracts/BondingCurve/curve/bancor-formula/Power.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pragma solidity >= 0.4.22 <6.0.0;
import "zos-lib/contracts/Initializable.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";

/**
* bancor formula by bancor
Expand Down
8 changes: 4 additions & 4 deletions contracts/BondingCurve/dividend/DividendPool.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pragma solidity ^0.5.4;
pragma solidity ^0.5.7;

import "zos-lib/contracts/Initializable.sol";
import "openzeppelin-eth/contracts/token/ERC20/IERC20.sol";
import "@statesauce/merkle-payments/contracts/PaymentPool.sol";
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol";
import "./PaymentPool.sol";

/**
* @title Dividend Payment Pool
Expand Down
Loading