Merge pull request #65 from nfnty/curve_params

DynamicCeiling: Implement `slopeFactor` and `collectMinimum` per curve
This commit is contained in:
Jarrad 2017-06-14 11:26:49 +08:00 committed by GitHub
commit 42f7a11702
6 changed files with 44 additions and 24 deletions

View File

@ -35,15 +35,15 @@ contract DynamicCeiling is Owned {
struct Curve {
bytes32 hash;
// Absolute limit for this curve
uint256 limit;
// The funds remaining to be collected are divided by `slopeFactor` smooth ceiling
// with a long tail where big and small buyers can take part.
uint256 slopeFactor;
// This keeps the curve flat at this number, until funds to be collected is less than this
uint256 collectMinimum;
}
// The funds remaining to be collected are divided by `slopeFactor` smooth ceiling
// with a long tail where big and small buyers can take part.
uint256 constant public slopeFactor = 30;
// This keeps the curve flat at this number, until funds to be collected is less than this
uint256 constant public collectMinimum = 10**15;
address public contribution;
Curve[] public curves;
@ -84,16 +84,21 @@ contract DynamicCeiling is Owned {
/// (must be greater or equal to the previous one).
/// @param _last `true` if it's the last curve.
/// @param _salt Random number used to commit the curve
function revealCurve(uint256 _limit, bool _last, bytes32 _salt) public {
function revealCurve(uint256 _limit, uint256 _slopeFactor, uint256 _collectMinimum,
bool _last, bytes32 _salt) public {
if (allRevealed) throw;
if (curves[revealedCurves].hash != keccak256(_limit, _last, _salt)) throw;
if (curves[revealedCurves].hash != keccak256(_limit, _slopeFactor, _collectMinimum,
_last, _salt)) throw;
if (_limit == 0 || _slopeFactor == 0 || _collectMinimum == 0) throw;
if (revealedCurves > 0) {
if (_limit < curves[revealedCurves.sub(1)].limit) throw;
}
curves[revealedCurves].limit = _limit;
curves[revealedCurves].slopeFactor = _slopeFactor;
curves[revealedCurves].collectMinimum = _collectMinimum;
revealedCurves = revealedCurves.add(1);
if (_last) allRevealed = true;
@ -123,12 +128,12 @@ contract DynamicCeiling is Owned {
uint256 difference = curves[currentIndex].limit.sub(collected);
// Current point on the curve
uint256 collect = difference.div(slopeFactor);
uint256 collect = difference.div(curves[currentIndex].slopeFactor);
// Prevents paying too much fees vs to be collected; breaks long tail
if (collect <= collectMinimum) {
if (difference > collectMinimum) {
return collectMinimum;
if (collect <= curves[currentIndex].collectMinimum) {
if (difference > curves[currentIndex].collectMinimum) {
return curves[currentIndex].collectMinimum;
} else {
return difference;
}
@ -142,8 +147,9 @@ contract DynamicCeiling is Owned {
/// @param _last `true` if it's the last curve.
/// @param _salt Random number that will be needed to reveal this curve.
/// @return The calculated hash of this curve to be used in the `setHiddenCurves` method
function calculateHash(uint256 _limit, bool _last, bytes32 _salt) public constant returns (bytes32) {
return keccak256(_limit, _last, _salt);
function calculateHash(uint256 _limit, uint256 _slopeFactor, uint256 _collectMinimum,
bool _last, bytes32 _salt) public constant returns (bytes32) {
return keccak256(_limit, _slopeFactor, _collectMinimum, _last, _salt);
}
/// @return Return the total number of curves committed

View File

@ -290,7 +290,7 @@ contract StatusContribution is Owned, TokenController {
// Allow premature finalization if final limit is reached
if (getBlockNumber() <= endBlock) {
var (,lastLimit) = dynamicCeiling.curves(dynamicCeiling.revealedCurves().sub(1));
var (,lastLimit,,) = dynamicCeiling.curves(dynamicCeiling.revealedCurves().sub(1));
if (totalNormalCollected < lastLimit) throw;
}

View File

@ -32,9 +32,9 @@ contract("StatusContribution", (accounts) => {
let externalToken;
const curves = [
[web3.toWei(3)],
[web3.toWei(13)],
[web3.toWei(15)],
[web3.toWei(3), 30, 10**12],
[web3.toWei(13), 30, 10**12],
[web3.toWei(15), 30, 10**12],
];
const startBlock = 1000000;
const endBlock = 1003000;

View File

@ -33,9 +33,9 @@ contract("StatusContribution", (accounts) => {
const divs = 30;
const curves = [
[web3.toWei(3)],
[web3.toWei(8)],
[web3.toWei(15)],
[web3.toWei(3), 30, 10**12],
[web3.toWei(8), 30, 10**12],
[web3.toWei(15), 30, 10**12],
];
const startBlock = 1000000;
const endBlock = 1030000;
@ -120,6 +120,8 @@ contract("StatusContribution", (accounts) => {
it("Reveal a curve, move time to start of the ICO, and do the first buy", async () => {
await dynamicCeiling.revealCurve(
curves[0][0],
curves[0][1],
curves[0][2],
false,
web3.sha3("pwd0"));
@ -165,6 +167,8 @@ contract("StatusContribution", (accounts) => {
it("Should reveal second curve and check that every that the limit is right", async () => {
await dynamicCeiling.revealCurve(
curves[1][0],
curves[1][1],
curves[1][2],
false,
web3.sha3("pwd1"));
await dynamicCeiling.moveTo(1);
@ -195,6 +199,8 @@ contract("StatusContribution", (accounts) => {
it("Should reveal last curve, fill the collaboration", async () => {
await dynamicCeiling.revealCurve(
curves[2][0],
curves[2][1],
curves[2][2],
true,
web3.sha3("pwd2"));
await dynamicCeiling.moveTo(2);

View File

@ -7,9 +7,9 @@ contract("DynamicCeiling", (accounts) => {
let dynamicCeiling;
const curves = [
[web3.toWei(1000)],
[web3.toWei(21000)],
[web3.toWei(61000)],
[web3.toWei(1000), 30, 10**12],
[web3.toWei(21000), 30, 10**12],
[web3.toWei(61000), 30, 10**12],
];
it("Should deploy dynamicCeiling", async () => {
@ -54,6 +54,8 @@ contract("DynamicCeiling", (accounts) => {
it("Should reveal 1st curve", async () => {
await dynamicCeiling.revealCurve(
curves[0][0],
curves[0][1],
curves[0][2],
false,
web3.sha3("pwd0"));
@ -86,6 +88,8 @@ contract("DynamicCeiling", (accounts) => {
it("Should reveal 2nd curve", async () => {
await dynamicCeiling.revealCurve(
curves[1][0],
curves[1][1],
curves[1][2],
false,
web3.sha3("pwd1"));
@ -119,6 +123,8 @@ contract("DynamicCeiling", (accounts) => {
it("Should reveal last curve", async () => {
await dynamicCeiling.revealCurve(
curves[2][0],
curves[2][1],
curves[2][2],
true,
web3.sha3("pwd2"));

View File

@ -4,6 +4,8 @@ exports.setHiddenCurves = async (dynamicCeiling, curves) => {
for (let c of curves) {
const h = await dynamicCeiling.calculateHash(
c[0],
c[1],
c[2],
i === curves.length - 1,
web3.sha3(`pwd${ i }`));
hashes.push(h);