1# IndividuallyCappedCrowdsale
2# Contributors: Binod Nirvan
3# This file is released under Apache 2.0 license.
4# @dev Crowdsale with a limit for total contributions.
5# Ported from Open Zeppelin
6# https://github.com/OpenZeppelin
7#
8# See https://github.com/OpenZeppelin
9# Open Zeppelin tests ported: Crowdsale.test.js
10
11
12#@dev ERC20/223 Features referenced by this contract
13contract TokenContract:
14    def transfer(_to: address, _value: uint256) -> bool: modifying
15
16# Event for token purchase logging
17# @param _purchaser who paid for the tokens
18# @param _beneficiary who got the tokens
19# @param _value weis paid for purchase
20# @param _amount amount of tokens purchased
21TokenPurchase: event({_purchaser: indexed(address), _beneficiary: indexed(address), _value: uint256(wei), _amount: uint256})
22
23# The token being sold
24token: public(address)
25
26#Address where funds are collected
27wallet: public(address)
28
29# How many token units a buyer gets per wei.
30# The rate is the conversion between wei and the smallest and indivisible token unit.
31# So, if you are using a rate of 1 with a DetailedERC20 token with 3 decimals called TOK
32# 1 wei will give you 1 unit, or 0.001 TOK.
33rate: public(uint256)
34
35#Amount of wei raised
36weiRaised: public(uint256(wei))
37
38@public
39def __init__(_rate: uint256, _wallet: address, _token: address):
40    """
41    @dev Initializes this contract
42    @param _rate Number of token units a buyer gets per wei
43    @param _wallet Address where collected funds will be forwarded to
44    @param _token Address of the token being sold
45    """
46
47    assert _rate > 0, "Invalid value supplied for the parameter \"_rate\"."
48    assert _wallet != ZERO_ADDRESS, "Invalid wallet address."
49    assert _token != ZERO_ADDRESS, "Invalid token address."
50
51    self.rate = _rate
52    self.wallet = _wallet
53    self.token = _token
54
55@private
56@constant
57def getTokenAmount(_weiAmount: uint256) -> uint256:
58    return _weiAmount * self.rate
59
60
61@private
62def processTransaction(_sender: address, _beneficiary: address, _weiAmount: uint256(wei)):
63    #pre validate
64    assert _beneficiary != ZERO_ADDRESS, "Invalid address."
65    assert _weiAmount != 0, "Invalid amount received."
66
67    #calculate the number of tokens for the Ether contribution.
68    tokens: uint256 = self.getTokenAmount(as_unitless_number(_weiAmount))
69
70    self.weiRaised += _weiAmount
71
72    #process purchase
73    assert TokenContract(self.token).transfer(_beneficiary, tokens), "Could not forward funds due to an unknown error."
74    log.TokenPurchase(_sender, _beneficiary, _weiAmount, tokens)
75
76    #forward funds to the receiving wallet address.
77    send(self.wallet, _weiAmount)
78
79    #post validate
80
81@public
82@payable
83def buyTokens(_beneficiary: address):
84    self.processTransaction(msg.sender, _beneficiary, msg.value)
85
86@public
87@payable
88def __default__():
89    self.processTransaction(msg.sender, msg.sender, msg.value)
90