Skip to content

Commit

Permalink
Added ETH capped miting crowdsale.
Browse files Browse the repository at this point in the history
  • Loading branch information
miohtama committed May 15, 2017
1 parent f682aef commit ed985be
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 1 deletion.
40 changes: 40 additions & 0 deletions contracts/MintedEthCappedCrowdsale.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
pragma solidity ^0.4.8;

import "./Crowdsale.sol";
import "./MintableToken.sol";

/**
* ICO crowdsale contract that is capped by amout of ETH.
*
* - Tokens are dynamically created during the crowdsale
*
*
*/
contract MintedEthCappedCrowdsale is Crowdsale {

/* Maximum amount of wei this crowdsale can raise. */
uint public weiCap;

function MintedEthCappedCrowdsale(address _token, PricingStrategy _pricingStrategy, address _multisigWallet, uint _start, uint _end, uint _minimumFundingGoal, uint _weiCap) Crowdsale(_token, _pricingStrategy, _multisigWallet, _start, _end, _minimumFundingGoal) {
weiCap = _weiCap;
}

/**
* Called from invest() to confirm if the curret investment does not break our cap rule.
*/
function isBreakingCap(uint weiAmount, uint tokenAmount, uint weiRaisedTotal, uint tokensSoldTotal) constant returns (bool limitBroken) {
return weiRaisedTotal > weiCap;
}

function isCrowdsaleFull() public constant returns (bool) {
return weiRaised >= weiCap;
}

/**
* Dynamically create tokens and assign them to the investor.
*/
function assignTokens(address receiver, uint tokenAmount) private {
MintableToken mintableToken = MintableToken(token);
mintableToken.mint(receiver, tokenAmount);
}
}
160 changes: 160 additions & 0 deletions ico/tests/contracts/test_eth_capped.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
"""Token capped crowdsale."""
import datetime

import pytest
from eth_utils import from_wei
from eth_utils import to_wei
from ethereum.tester import TransactionFailed
from web3.contract import Contract

from ico.tests.utils import time_travel
from ico.state import CrowdsaleState


@pytest.fixture
def token(empty_token):
"""Get a token with 0 initial issuance."""
return empty_token


@pytest.fixture
def start_time() -> int:
"""Start Apr 15th"""
return int((datetime.datetime(2017, 4, 15, 16, 00) - datetime.datetime(1970, 1, 1)).total_seconds())


@pytest.fixture
def end_time(start_time) -> int:
"""Run 4 weeks."""
return start_time + 4 * 7 * 24 * 3600


@pytest.fixture
def minimum_funding_goal() -> int:
"""What is our minimum funding goal."""
return to_wei(7500, "ether")


@pytest.fixture
def cap() -> int:
"""What is our maximum tokens sold capacity."""
return to_wei(888888, "ether")


@pytest.fixture
def founder_allocation() -> float:
"""How much tokens are allocated to founders, etc."""
return 7.0/3.0


@pytest.fixture
def pricing_strategy(chain, start_time, end_time, team_multisig):

week = 24*3600 * 7

args = [
to_wei(1, "ether")
]

tx = {
"from": team_multisig,
}

contract, hash = chain.provider.deploy_contract('FlatPricing', deploy_args=args, deploy_transaction=tx)
return contract


@pytest.fixture
def crowdsale(chain, team_multisig, start_time, end_time, pricing_strategy, preico_cap, minimum_funding_goal, cap, token) -> Contract:
"""Create a crowdsale contract that has a minting cap and bonus % and token sold limit."""

args = [
token.address,
pricing_strategy.address,
team_multisig,
start_time,
end_time,
minimum_funding_goal,
cap
]

tx = {
"from": team_multisig,
}

contract, hash = chain.provider.deploy_contract('MintedEthCappedCrowdsale', deploy_args=args, deploy_transaction=tx)

assert contract.call().owner() == team_multisig
assert not token.call().released()
assert contract.call().weiCap() == cap

# Allow crowdsale contract to do mint()
token.transact({"from": team_multisig}).setMintAgent(contract.address, True)
assert token.call().mintAgents(contract.address) == True

return contract


@pytest.fixture()
def finalizer(chain, token, crowdsale, team_multisig, founder_allocation) -> Contract:

# Create finalizer contract
args = [
token.address,
crowdsale.address,
int(founder_allocation * 10000), # 20% for founders, bounties, etc.
team_multisig, # Who gets extra tokens
]
contract, hash = chain.provider.deploy_contract('BonusFinalizeAgent', deploy_args=args)

# Set crowdsale finalizer

# Allow finalzier to do mint()
token.transact({"from": team_multisig}).setMintAgent(contract.address, True)
assert token.call().mintAgents(contract.address) == True

token.transact({"from": team_multisig}).setReleaseAgent(contract.address)

crowdsale.transact({"from": team_multisig}).setFinalizeAgent(contract.address)

return contract


def test_buy_all(chain, web3, crowdsale, token, finalizer, start_time, end_time, team_multisig, customer, cap, founder_allocation):
"""Buy all tokens and finalize crowdsale."""

# Buy on first week
time_travel(chain, start_time + 1)
assert crowdsale.call().getState() == CrowdsaleState.Funding

# Buy all cap
wei_value = cap
print(from_wei(web3.eth.getBalance(customer), "ether"))
crowdsale.transact({"from": customer, "value": wei_value}).buy()
assert crowdsale.call().isCrowdsaleFull()

# Close the deal
time_travel(chain, end_time + 1)
assert crowdsale.call().getState() == CrowdsaleState.Success
crowdsale.transact({"from": team_multisig}).finalize()
assert crowdsale.call().getState() == CrowdsaleState.Finalized

# See that we counted bonus correctly
team_bonus = token.call().totalSupply() * 7 / 10
assert abs(finalizer.call().allocatedBonus() - team_bonus) < 10 # We lose some in decimal rounding

# Token is transferable
assert token.call().released()


def test_buy_all_plus_one(chain, web3, crowdsale, token, finalizer, start_time, end_time, team_multisig, customer, cap, founder_allocation):
"""Buy too many tokens."""

# Buy on first week
time_travel(chain, start_time + 1)
assert crowdsale.call().getState() == CrowdsaleState.Funding

# Buy all cap
wei_value = cap + 1
with pytest.raises(TransactionFailed):
crowdsale.transact({"from": customer, "value": wei_value}).buy()
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Minted and capped crowdsale."""
"""Token capped crowdsale."""
import datetime

import pytest
Expand Down

0 comments on commit ed985be

Please sign in to comment.