5

I had a look at some existing crowdsale contracts:

Below is an ASCII graph from Aragon source code. Rather than stages, I'd like to find a contract that implements linear or logarithmic decrease in the amount of tokens...

enter image description here

  • For the first time I've used rollback function to undo the edit - full URL to github is much more informative than some formatted link. – Mars Robertson Jul 26 '17 at 14:59
3

Let's suppose we have M the maximum amount of tokens to sell, I the initial price of each token and F the final price of each token. Let's call f the function that gives the price of each token, we know that f(0) = I and f(M) = F. If you want a linear price then f(x) = I + (F - I) * x / M.

The problem is to determine how many token we will get when we pay V and there's already K tokens sold. Let's say we will get D tokens, we know our initial price will be f(K) and the final prize f(K + D), and the total price will be the are under the graph. Yeah math!

Token price function of the emited tokens

So we will have the equation

Cost of D tokens from K

To determine the amount of tokens to sell for V ethers we have to solve the 2nd degree equation (F-I)D2+ 2(MI + (F-I)K)D - 2MV = 0. Yeah, more math!

 (-b +/- sqrt(b^2 - 4ac))/(2a)

For example in the plot I've I=100, F=225, M=500. Then when there are K=150 for 1000 ethers we will get:

D = (-2*(50000+125*k)+sqrt(4*(50000+125*k)**2 + 500000*v))/250 = 7.225268630201346

(the other solution for D is negative)

If we want to purchase 10 token when 150 were sold already we have to pay (K=150, D=10)

V = ID + (F-I)*(2KD + D^2)/(2M)
V = 1000 + 125*(20*150 + 100)/1000
V = 1387.5

To calculate the total recaudation we set K=0, D=500

V = 100*500 + 125*(500^2)/(2*500)
V = 81250.0

We can verify this is the area of the plot.

1

Solidity code based on the solution by @Ismael, assumes linear increase in price.

// tokens sold
uint256 tokensSold;
// tokens to be sold in total

uint tokensToBeSold = 100000000*(10**18);
uint ip = 5000;
uint fp = 10000;
// final price - initial price
uint256 pd = fp - ip;
// total supply * initial price
uint256 tsip = tokensToBeSold * ip;

// helper token emission functions
function howMany(uint256 value) public returns (uint256){
    uint256 a = sqrt(4 * ((tsip + pd * tokensSold) ** 2) + value.mul(8 * pd * tokensToBeSold));
    uint256 b = 2 * (tsip + pd* tokensSold);
    uint256 c = 2 * pd;

    // get a result with
    return round(((a - b)* 10) / c);
}

// Rounding function for the first decimal
function round(uint x) internal returns (uint y) {
    uint z = x % 10;

    if (z < 5) {
        return x / 10;
    }

    else {
        return (x / 10) + 1;
    }
}

// Squareroot implementation
function sqrt(uint x) internal returns (uint y) {
    uint z = (x + 1) / 2;
    y = x;
    while (z < y) {
        y = z;
        z = (x / z + z) / 2;
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.