diff --git a/.gitignore b/.gitignore index d76190e..0c23794 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -**/chain_db/ \ No newline at end of file +**/chain_db/ +node_modules/ diff --git a/env.js b/env.js new file mode 100644 index 0000000..7054ccc --- /dev/null +++ b/env.js @@ -0,0 +1,84 @@ + +var Web3 = require('web3'); +// create an instance of web3 using the HTTP provider. +// NOTE in mist web3 is already available, so check first if its available before instantiating +var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + +var BigNumber = require('bignumber.js'); + +var eth = web3.eth; + +//////////////////////// +/// Deploy crowdsale +//////////////////////// + +var now = Math.floor(new Date().getTime() / 1000) + +var _exitAddress = eth.accounts[1]; +var _startSale = now + 300 ; // StartOf the sale +// var _startSale = 1487919600 ; // StartOf the sale +var _limitVIP = web3.toWei(5000) ; +var crowdFundAbi = [{"constant":true,"inputs":[],"name":"creator","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalETH","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalVIP","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"limitVIP","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"recipientETH","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"}],"name":"purchaseMembership","outputs":[],"payable":true,"type":"function"},{"constant":true,"inputs":[],"name":"exitAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_legendsToken","type":"address"}],"name":"setTokenContract","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"start","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"legendsToken","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"recipientVIP","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"_exitAddress","type":"address"},{"name":"_start","type":"uint256"},{"name":"_limitVIP","type":"uint256"}],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":true,"name":"recipient","type":"address"},{"indexed":false,"name":"ETH","type":"uint256"},{"indexed":false,"name":"VIP","type":"uint256"}],"name":"VIPPurchase","type":"event"}]; +var crowdFundContract = web3.eth.contract(crowdFundAbi); +var crowdFund = crowdFundContract.new( + _exitAddress, + _startSale, + _limitVIP, + { + from: web3.eth.accounts[0], + data: '0x6060604052341561000c57fe5b60405160608061058a8339810160409081528151602083015191909201515b60008054600160a060020a03338116600160a060020a0319928316179092556001805492861692909116919091179055600282905560038190555b5050505b610511806100796000396000f300606060405236156100935763ffffffff60e060020a60003504166302d05d3f811461009557806336bdee74146100c1578063407a6727146100e3578063416ccd02146101055780634c12d8b914610127578063665c0b8e146101555780636be002291461016b578063bbcd5bbe14610197578063be9a6555146101b5578063c851b643146101d7578063cc6da37514610203575bfe5b341561009d57fe5b6100a5610231565b60408051600160a060020a039092168252519081900360200190f35b34156100c957fe5b6100d1610240565b60408051918252519081900360200190f35b34156100eb57fe5b6100d1610246565b60408051918252519081900360200190f35b341561010d57fe5b6100d161024c565b60408051918252519081900360200190f35b341561012f57fe5b6100d1600160a060020a0360043516610252565b60408051918252519081900360200190f35b610169600160a060020a0360043516610264565b005b341561017357fe5b6100a5610450565b60408051600160a060020a039092168252519081900360200190f35b341561019f57fe5b610169600160a060020a036004351661045f565b005b34156101bd57fe5b6100d16104be565b60408051918252519081900360200190f35b34156101df57fe5b6100a56104c4565b60408051600160a060020a039092168252519081900360200190f35b341561020b57fe5b6100d1600160a060020a03600435166104d3565b60408051918252519081900360200190f35b600054600160a060020a031681565b60075481565b60085481565b60035481565b60056020526000908152604090205481565b600454600090600160a060020a0316151561027e57610000565b60025442101561028d57610000565b34151561029957610000565b81600160a060020a03811615806102c1575030600160a060020a031681600160a060020a0316145b156102cb57610000565b600154604051600160a060020a03909116903480156108fc02916000818181858888f1935050505015156102fe57610000565b600160a060020a03831660009081526005602052604090208054349081019091556007805482019055600254600a9091029250621275004291909103101561034b576009600a83025b0491505b600160a060020a03831660009081526006602052604090208054830190556008805483019081905560035490111561038257610000565b60048054604080517f6039fbdb000000000000000000000000000000000000000000000000000000008152600160a060020a03878116948201949094526024810186905290519290911691636039fbdb9160448082019260009290919082900301818387803b15156103f057fe5b60325a03f115156103fd57fe5b505060408051348152602081018590528151600160a060020a0380881694503316927fa8b57f15ffe511f633f9bd512e6fdb2e692b54ff870617cfcc2f63f1f1b1d326928290030190a35b5b505b5b5050565b600154600160a060020a031681565b60005433600160a060020a0390811691161461047a57610000565b600454600160a060020a03161561049057610000565b6004805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b5b50565b60025481565b600454600160a060020a031681565b600660205260009081526040902054815600a165627a7a7230582035ac4e942bd9eac49aef0718a580e3c83c8f3bca69a20582c5297c599e4f8ebc0029', + gas: '3900000', + gasPrice: eth.gasPrice*2 + }, function (e, contract){ + console.log(e, contract); + if (typeof contract.address !== 'undefined') { + console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); + } + }); + + +//////////////////////// +/// Deploy token +//////////////////////// + +var _legendsCrowdfund = crowdFund.address ; +var _preallocation = eth.accounts[2] ; +// var _endSale = _startSale + 86400 * 30; // Start of the transfers (End of the sale) +var _endSale = _startSale + 1800; // Start of the transfers (End of the sale) +var _testing = false ; +var tokenAbi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"totalSupply","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalVIP","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"},{"name":"VIP","type":"uint256"}],"name":"addTokens","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"legendsCrowdfund","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"testing","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"start","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"_legendsCrowdfund","type":"address"},{"name":"_preallocation","type":"address"},{"name":"_start","type":"uint256"},{"name":"_testing","type":"bool"}],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipient","type":"address"},{"indexed":false,"name":"VIP","type":"uint256"}],"name":"TokensAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]; +var tokenContract = web3.eth.contract(tokenAbi); +var token = tokenContract.new( + _legendsCrowdfund, + _preallocation, + _endSale, + _testing, + { + from: web3.eth.accounts[0], + data: '0x60a0604052600360608190527f5649500000000000000000000000000000000000000000000000000000000000608090815261003e916000919061017a565b506001805460ff1916811790556040805180820190915260038082527f5649500000000000000000000000000000000000000000000000000000000000602090920191825261008f9160029161017a565b506040805180820190915260078082527f5649505f302e310000000000000000000000000000000000000000000000000060209092019182526100d49160039161017a565b5034156100dd57fe5b604051608080610ce483398101604090815281516020830151918301516060909301519092905b600880546007849055600160a060020a031916600160a060020a038681169190911760a060020a60ff0219167401000000000000000000000000000000000000000084151502179091558316600090815260046020526040902069054b40b1f852bda00000908190556006555b5050505061021a565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106101bb57805160ff19168380011785556101e8565b828001600101855582156101e8579182015b828111156101e85782518255916020019190600101906101cd565b5b506101f59291506101f9565b5090565b61021791905b808211156101f557600081556001016101ff565b5090565b90565b610abb806102296000396000f300606060405236156100bf5763ffffffff60e060020a60003504166306fdde038114610140578063095ea7b3146101d057806318160ddd1461020357806323b872dd14610225578063313ce5671461025e578063407a67271461028457806354fd4d50146102a65780636039fbdb14610336578063642231a61461035757806370a08231146103835780638d03b102146103b157806395d89b41146103d5578063a9059cbb14610465578063be9a655514610498578063dd62ed3e146104ba575b61013e5b600854604080517f665c0b8e000000000000000000000000000000000000000000000000000000008152600160a060020a0333811660048301529151919092169163665c0b8e91349160248082019260009290919082900301818588803b151561012957fe5b61235a5a03f1151561013757fe5b505050505b565b005b341561014857fe5b6101506104ee565b604080516020808252835181830152835191928392908301918501908083838215610196575b80518252602083111561019657601f199092019160209182019101610176565b505050905090810190601f1680156101c25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156101d857fe5b6101ef600160a060020a036004351660243561057c565b604080519115158252519081900360200190f35b341561020b57fe5b610213610638565b60408051918252519081900360200190f35b341561022d57fe5b6101ef600160a060020a036004358116906024351660443561063f565b604080519115158252519081900360200190f35b341561026657fe5b61026e610771565b6040805160ff9092168252519081900360200190f35b341561028c57fe5b61021361077a565b60408051918252519081900360200190f35b34156102ae57fe5b610150610780565b604080516020808252835181830152835191928392908301918501908083838215610196575b80518252602083111561019657601f199092019160209182019101610176565b505050905090810190601f1680156101c25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561033e57fe5b61013e600160a060020a036004351660243561080e565b005b341561035f57fe5b6103676108b1565b60408051600160a060020a039092168252519081900360200190f35b341561038b57fe5b610213600160a060020a03600435166108c0565b60408051918252519081900360200190f35b34156103b957fe5b6101ef6108df565b604080519115158252519081900360200190f35b34156103dd57fe5b6101506108ef565b604080516020808252835181830152835191928392908301918501908083838215610196575b80518252602083111561019657601f199092019160209182019101610176565b505050905090810190601f1680156101c25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561046d57fe5b6101ef600160a060020a036004351660243561097a565b604080519115158252519081900360200190f35b34156104a057fe5b610213610a5c565b60408051918252519081900360200190f35b34156104c257fe5b610213600160a060020a0360043581169060243516610a62565b60408051918252519081900360200190f35b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105745780601f1061054957610100808354040283529160200191610574565b820191906000526020600020905b81548152906001019060200180831161055757829003601f168201915b505050505081565b600060075442101561058d57610000565b828280158015906105c25750600160a060020a0333811660009081526005602090815260408083209386168352929052205415155b156105cc57610000565b600160a060020a033381166000818152600560209081526040808320948a1680845294825291829020889055815188815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3600192505b5b50505b92915050565b6006545b90565b600060075442101561065057610000565b82600160a060020a0381161580610678575030600160a060020a031681600160a060020a0316145b1561068257610000565b600160a060020a03808616600090815260056020908152604080832033909416835292905220548390108015906106d25750600160a060020a038516600090815260046020526040902054839010155b1561076157600160a060020a03808516600081815260046020908152604080832080548901905589851680845281842080548a90039055600583528184203390961684529482529182902080548890039055815187815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a360019150610766565b600091505b5b5b505b9392505050565b60015460ff1681565b60065481565b6003805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105745780601f1061054957610100808354040283529160200191610574565b820191906000526020600020905b81548152906001019060200180831161055757829003601f168201915b505050505081565b60085460a060020a900460ff1615801561082a57506007544210155b1561083457610000565b60085433600160a060020a0390811691161461084f57610000565b600160a060020a0382166000818152600460209081526040918290208054850190556006805485019055815184815291517f0eaac1064ee8d13f83091f388597ffb5ff2d2e59f6a16aae2a74ba7f2d13c8d99281900390910190a25b5b5b5050565b600854600160a060020a031681565b600160a060020a0381166000908152600460205260409020545b919050565b60085460a060020a900460ff1681565b6002805460408051602060018416156101000260001901909316849004601f810184900484028201840190925281815292918301828280156105745780601f1061054957610100808354040283529160200191610574565b820191906000526020600020905b81548152906001019060200180831161055757829003601f168201915b505050505081565b600060075442101561098b57610000565b82600160a060020a03811615806109b3575030600160a060020a031681600160a060020a0316145b156109bd57610000565b600160a060020a033316600090815260046020526040902054839010610a4d57600160a060020a03338116600081815260046020908152604080832080548990039055938816808352918490208054880190558351878152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a360019150610a52565b600091505b5b5b505b92915050565b60075481565b600160a060020a038083166000908152600560209081526040808320938516835292905220545b929150505600a165627a7a7230582080aeaaf7894ca7ae3051609c5df2611c0d4b0406bf01d061d31830754a995d850029', + gas: '3900000', + gasPrice: eth.gasPrice*2 + }, function (e, contract){ + console.log(e, contract); + if (typeof contract.address !== 'undefined') { + console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); + } + }); + + +//////////////////// +/// Set token in the crowdsale +//////////////////// + +crowdFund.setTokenContract(token.address, {from: eth.accounts[0]}); + + +////////////////////// +/// Helper visualization +////////////////////// +crowdFund.start().toNumber() - new Date().getTime()/1000 +token.start().toNumber() - new Date().getTime()/1000 + +web3.fromWei(token.balanceOf(eth.accounts[1])).toNumber() + + diff --git a/legends_token.sol b/legends_token.sol index 9069d11..903ec72 100644 --- a/legends_token.sol +++ b/legends_token.sol @@ -2,17 +2,25 @@ pragma solidity ^0.4.9; import "./erc20.sol"; +contract LegendsCrowdfund { + function purchaseMembership(address recipient) payable; +} + /** * @title LegendsToken */ contract LegendsToken is ERC20 { + string public name = 'VIP'; //The Token's name: e.g. DigixDAO Tokens + uint8 public decimals = 18; // 1Token ¨= 1$ (1ETH ¨= 10$) + string public symbol = 'VIP'; //An identifier: e.g. REP + string public version = 'VIP_0.1'; mapping (address => uint) ownerVIP; mapping (address => mapping (address => uint)) allowed; uint public totalVIP; uint public start; - + address public legendsCrowdfund; bool public testing; @@ -23,7 +31,7 @@ contract LegendsToken is ERC20 { } _; } - + modifier isActive() { if (block.timestamp < start) { throw; @@ -45,20 +53,6 @@ contract LegendsToken is ERC20 { _; } - modifier senderHasSufficient(uint VIP) { - if (ownerVIP[msg.sender] < VIP) { - throw; - } - _; - } - - modifier transferApproved(address from, uint VIP) { - if (allowed[from][msg.sender] < VIP || ownerVIP[from] < VIP) { - throw; - } - _; - } - modifier allowanceIsZero(address spender, uint value) { // To change the approve amount you first have to reduce the addresses´ // allowance to zero by calling `approve(_spender,0)` if it is not @@ -89,7 +83,7 @@ contract LegendsToken is ERC20 { testing = _testing; totalVIP = ownerVIP[_preallocation] = 25000 ether; } - + /** * @dev Add to token balance on address. Must be from crowdfund. * @param recipient Address to add tokens to. @@ -118,22 +112,30 @@ contract LegendsToken is ERC20 { /** * @dev Implements ERC20 transfer() */ - function transfer(address _to, uint256 _value) isActive recipientIsValid(_to) senderHasSufficient(_value) returns (bool success) { - ownerVIP[msg.sender] -= _value; - ownerVIP[_to] += _value; - Transfer(msg.sender, _to, _value); - return true; + function transfer(address _to, uint256 _value) isActive recipientIsValid(_to) returns (bool success) { + if (ownerVIP[msg.sender] >= _value) { + ownerVIP[msg.sender] -= _value; + ownerVIP[_to] += _value; + Transfer(msg.sender, _to, _value); + return true; + } else { + return false; + } } /** * @dev Implements ERC20 transferFrom() */ - function transferFrom(address _from, address _to, uint256 _value) isActive recipientIsValid(_to) transferApproved(_from, _value) returns (bool success) { - ownerVIP[_to] += _value; - ownerVIP[_from] -= _value; - allowed[_from][msg.sender] -= _value; - Transfer(_from, _to, _value); - return true; + function transferFrom(address _from, address _to, uint256 _value) isActive recipientIsValid(_to) returns (bool success) { + if (allowed[_from][msg.sender] >= _value && ownerVIP[_from] >= _value) { + ownerVIP[_to] += _value; + ownerVIP[_from] -= _value; + allowed[_from][msg.sender] -= _value; + Transfer(_from, _to, _value); + return true; + } else { + return false; + } } /** @@ -152,4 +154,11 @@ contract LegendsToken is ERC20 { remaining = allowed[_owner][_spender]; } + /** + * @dev Direct Buy + */ + function () payable { + LegendsCrowdfund(legendsCrowdfund).purchaseMembership.value(msg.value)(msg.sender); + } + } diff --git a/package.json b/package.json new file mode 100644 index 0000000..ad5e86e --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "vipsalecontract", + "version": "0.0.1", + "description": "VIP sale contract", + "main": "env.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/jbaylina/VIP.git" + }, + "keywords": [ + "VIP", + "contract", + "ethereum" + ], + "author": "Jordi Baylina", + "license": "GPL-3.0", + "bugs": { + "url": "https://github.com/jbaylina/VIP/issues" + }, + "homepage": "https://github.com/jbaylina/VIP#readme", + "dependencies": { + "web3": "^0.18.2" + } +}