mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			157 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
| /*
 | |
| This file is part of the DAO.
 | |
| 
 | |
| The DAO is free software: you can redistribute it and/or modify
 | |
| it under the terms of the GNU lesser General Public License as published by
 | |
| the Free Software Foundation, either version 3 of the License, or
 | |
| (at your option) any later version.
 | |
| 
 | |
| The DAO is distributed in the hope that it will be useful,
 | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| GNU lesser General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU lesser General Public License
 | |
| along with the DAO.  If not, see <http://www.gnu.org/licenses/>.
 | |
| */
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Token Creation contract, used by the DAO to create its tokens and initialize
 | |
|  * its ether. Feel free to modify the divisor method to implement different
 | |
|  * Token Creation parameters
 | |
| */
 | |
| 
 | |
| import "./Token.sol";
 | |
| import "./ManagedAccount.sol";
 | |
| 
 | |
| abstract contract TokenCreationInterface {
 | |
| 
 | |
|     // End of token creation, in Unix time
 | |
|     uint public closingTime;
 | |
|     // Minimum fueling goal of the token creation, denominated in tokens to
 | |
|     // be created
 | |
|     uint public minTokensToCreate;
 | |
|     // True if the DAO reached its minimum fueling goal, false otherwise
 | |
|     bool public isFueled;
 | |
|     // For DAO splits - if privateCreation is 0, then it is a public token
 | |
|     // creation, otherwise only the address stored in privateCreation is
 | |
|     // allowed to create tokens
 | |
|     address public privateCreation;
 | |
|     // hold extra ether which has been sent after the DAO token
 | |
|     // creation rate has increased
 | |
|     ManagedAccount public extraBalance;
 | |
|     // tracks the amount of wei given from each contributor (used for refund)
 | |
|     mapping (address => uint256) weiGiven;
 | |
| 
 | |
|     /// @dev Constructor setting the minimum fueling goal and the
 | |
|     /// end of the Token Creation
 | |
|     /// @param _minTokensToCreate Minimum fueling goal in number of
 | |
|     ///        Tokens to be created
 | |
|     /// @param _closingTime Date (in Unix time) of the end of the Token Creation
 | |
|     /// @param _privateCreation Zero means that the creation is public.  A
 | |
|     /// non-zero address represents the only address that can create Tokens
 | |
|     /// (the address can also create Tokens on behalf of other accounts)
 | |
|     // This is the constructor: it can not be overloaded so it is commented out
 | |
|     //  function TokenCreation(
 | |
|         //  uint _minTokensTocreate,
 | |
|         //  uint _closingTime,
 | |
|         //  address _privateCreation
 | |
|         //  string _tokenName,
 | |
|         //  string _tokenSymbol,
 | |
|         //  uint _decimalPlaces
 | |
|     //  );
 | |
| 
 | |
|     /// @notice Create Token with `_tokenHolder` as the initial owner of the Token
 | |
|     /// @param _tokenHolder The address of the Tokens's recipient
 | |
|     /// @return success Whether the token creation was successful
 | |
|     function createTokenProxy(address payable _tokenHolder) payable virtual public returns (bool success);
 | |
| 
 | |
|     /// @notice Refund `msg.sender` in the case the Token Creation did
 | |
|     /// not reach its minimum fueling goal
 | |
|     function refund() virtual public;
 | |
| 
 | |
|     /// @return divisor The divisor used to calculate the token creation rate during
 | |
|     /// the creation phase
 | |
|     function divisor() public virtual view returns (uint divisor);
 | |
| 
 | |
|     event FuelingToDate(uint value);
 | |
|     event CreatedToken(address indexed to, uint amount);
 | |
|     event Refund(address indexed to, uint value);
 | |
| }
 | |
| 
 | |
| 
 | |
| contract TokenCreation is TokenCreationInterface, Token {
 | |
|     constructor(
 | |
|         uint _minTokensToCreate,
 | |
|         uint _closingTime,
 | |
|         address _privateCreation,
 | |
|         string memory _tokenName,
 | |
|         string memory _tokenSymbol,
 | |
|         uint8 _decimalPlaces) public {
 | |
| 
 | |
|         closingTime = _closingTime;
 | |
|         minTokensToCreate = _minTokensToCreate;
 | |
|         privateCreation = _privateCreation;
 | |
|         extraBalance = new ManagedAccount(address(this), true);
 | |
|         name = _tokenName;
 | |
|         symbol = _tokenSymbol;
 | |
|         decimals = _decimalPlaces;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     function createTokenProxy(address payable _tokenHolder) payable public
 | |
| override returns (bool success) {
 | |
|         if (block.timestamp < closingTime && msg.value > 0
 | |
|             && (privateCreation == 0x0000000000000000000000000000000000000000 || privateCreation == msg.sender)) {
 | |
| 
 | |
|             uint token = (msg.value * 20) / divisor();
 | |
|             address(extraBalance).call{value: msg.value - token}("");
 | |
|             balances[_tokenHolder] += token;
 | |
|             totalSupply += token;
 | |
|             weiGiven[_tokenHolder] += msg.value;
 | |
|             emit CreatedToken(_tokenHolder, token);
 | |
|             if (totalSupply >= minTokensToCreate && !isFueled) {
 | |
|                 isFueled = true;
 | |
|                 emit FuelingToDate(totalSupply);
 | |
|             }
 | |
|             return true;
 | |
|         }
 | |
|         revert();
 | |
|     }
 | |
| 
 | |
|     function refund() public override {
 | |
|         if (block.timestamp > closingTime && !isFueled) {
 | |
|             // Get extraBalance - will only succeed when called for the first time
 | |
|             if (address(extraBalance).balance >= extraBalance.accumulatedInput())
 | |
|                 extraBalance.payOut(payable(this), extraBalance.accumulatedInput());
 | |
| 
 | |
|             // Execute refund
 | |
|             (bool success,) = msg.sender.call{value: weiGiven[msg.sender]}("");
 | |
|             if (success) {
 | |
|                 emit Refund(msg.sender, weiGiven[msg.sender]);
 | |
|                 totalSupply -= balances[msg.sender];
 | |
|                 balances[msg.sender] = 0;
 | |
|                 weiGiven[msg.sender] = 0;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     function divisor() public override view returns (uint divisor) {
 | |
|         // The number of (base unit) tokens per wei is calculated
 | |
|         // as `msg.value` * 20 / `divisor`
 | |
|         // The fueling period starts with a 1:1 ratio
 | |
|         if (closingTime - 2 weeks > block.timestamp) {
 | |
|             return 20;
 | |
|         // Followed by 10 days with a daily creation rate increase of 5%
 | |
|         } else if (closingTime - 4 days > block.timestamp) {
 | |
|             return (20 + (block.timestamp - (closingTime - 2 weeks)) / (1 days));
 | |
|         // The last 4 days there is a constant creation rate ratio of 1:1.5
 | |
|         } else {
 | |
|             return 30;
 | |
|         }
 | |
|     }
 | |
|     receive() external virtual payable {
 | |
|     }
 | |
| }
 |