Merge pull request #65 from nfnty/curve_params
DynamicCeiling: Implement `slopeFactor` and `collectMinimum` per curve
This commit is contained in:
commit
42f7a11702
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue