From 81231c10860a208b2d25665ed1fe09f89253f412 Mon Sep 17 00:00:00 2001 From: alari Date: Mon, 7 Aug 2017 17:13:21 +0300 Subject: [PATCH] i --- .gitignore | 5 + contracts/ConvertLib.sol | 8 + contracts/FluencePreSale.sol | 261 ++++++++++++ contracts/MetaCoin.sol | 34 ++ contracts/Migrations.sol | 23 ++ migrations/1_initial_migration.js | 5 + migrations/2_deploy_contracts.js | 5 + package-lock.json | 649 ++++++++++++++++++++++++++++++ package.json | 11 + test/TestFluencePreSale.sol | 31 ++ test/TestMetacoin.sol | 25 ++ test/metacoin.js | 63 +++ truffle.js | 9 + 13 files changed, 1129 insertions(+) create mode 100644 .gitignore create mode 100644 contracts/ConvertLib.sol create mode 100644 contracts/FluencePreSale.sol create mode 100644 contracts/MetaCoin.sol create mode 100644 contracts/Migrations.sol create mode 100644 migrations/1_initial_migration.js create mode 100644 migrations/2_deploy_contracts.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 test/TestFluencePreSale.sol create mode 100644 test/TestMetacoin.sol create mode 100644 test/metacoin.js create mode 100644 truffle.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..caeb80a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/build +/.idea +*.iml +/node_modules +1501* \ No newline at end of file diff --git a/contracts/ConvertLib.sol b/contracts/ConvertLib.sol new file mode 100644 index 0000000..b97c88d --- /dev/null +++ b/contracts/ConvertLib.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.4.4; + +library ConvertLib{ + function convert(uint amount,uint conversionRate) returns (uint convertedAmount) + { + return amount * conversionRate; + } +} diff --git a/contracts/FluencePreSale.sol b/contracts/FluencePreSale.sol new file mode 100644 index 0000000..bf908ad --- /dev/null +++ b/contracts/FluencePreSale.sol @@ -0,0 +1,261 @@ +pragma solidity ^0.4.13; + + +/** + * Math operations with safety checks + */ +library SafeMath { + function mul(uint256 a, uint256 b) internal returns (uint256) { + uint256 c = a * b; + assert(a == 0 || c / a == b); + return c; + } + + function div(uint256 a, uint256 b) internal returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return c; + } + + function sub(uint256 a, uint256 b) internal returns (uint256) { + assert(b <= a); + return a - b; + } + + function add(uint256 a, uint256 b) internal returns (uint256) { + uint256 c = a + b; + assert(c >= a); + return c; + } + + function max64(uint64 a, uint64 b) internal constant returns (uint64) { + return a >= b ? a : b; + } + + function min64(uint64 a, uint64 b) internal constant returns (uint64) { + return a < b ? a : b; + } + + function max256(uint256 a, uint256 b) internal constant returns (uint256) { + return a >= b ? a : b; + } + + function min256(uint256 a, uint256 b) internal constant returns (uint256) { + return a < b ? a : b; + } + +} + + +/* + * Ownable + * + * Base contract with an owner. + * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner. + */ +contract Ownable { + address public owner; + + function Ownable() { + owner = msg.sender; + } + + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + function transferOwnership(address newOwner) onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + +/* + * Haltable + * + * Abstract contract that allows children to implement an + * emergency stop mechanism. Differs from Pausable by causing a throw when in halt mode. + * + * + * Originally envisioned in FirstBlood ICO contract. + */ +contract Haltable is Ownable { + bool public halted; + + modifier stopInEmergency { + require(!halted); + _; + } + + modifier onlyInEmergency { + require(halted); + _; + } + + // called by the owner on emergency, triggers stopped state + function halt() external onlyOwner { + halted = true; + } + + // called by the owner on end of emergency, returns to normal state + function unhalt() external onlyOwner onlyInEmergency { + halted = false; + } + +} + + +contract FluencePreSale is Haltable { + using SafeMath for uint; + using SafeMath for uint256; + + mapping (address => uint256) public balanceOf; + + /*/ + * Constants + /*/ + + string public constant name = "Fluence Presale Token"; + + string public constant symbol = "FPT"; + + uint public constant decimals = 18; + + // 6% of tokens + uint256 public constant SUPPLY_LIMIT = 6000000; + + // What is given to contributors, <= SUPPLY_LIMIT + uint256 public totalSupply; + + // If soft cap is not reached, refund process is started + uint256 public softCap = 1000 ether; + + // Basic price + uint public constant basicTokensPerEth = 1500; + + // Advanced price + uint256 public constant advancedThreshold = 5 ether; + uint public constant advancedTokensPerEth = 2250; + + // Expert price + uint256 public constant expertThreshold = 100 ether; + uint public constant expertTokensPerEth = 3000; + + // As we have different prices for different amounts, + // we keep a mapping of contributions to make refund + mapping (address => uint256) public etherContributions; + + // Max balance of the contract + uint256 public etherCollected; + + // Address to withdraw ether to + address public beneficiary; + + uint public startAtBlock; + + uint public endAtBlock; + + event GoalReached(uint amountRaised); + + event SoftCapReached(uint softCap); + + event NewContribution(address indexed holder, uint256 tokenAmount, uint256 etherAmount); + + event Refunded(address indexed holder, uint256 amount); + + // If soft cap is reached, withdraw should be available + modifier softCapReached { + require(etherCollected >= softCap); + _; + } + + modifier duringPresale { + require(block.number >= startAtBlock && block.number <= endAtBlock); + _; + } + + modifier duringRefund { + require(block.number > endAtBlock && etherCollected < softCap && this.balance > 0); + _; + } + + function FluencePreSale(uint _startAtBlock, uint _endAtBlock){ + require(_startAtBlock > 0 && _endAtBlock > 0); + beneficiary = msg.sender; + startAtBlock = _startAtBlock; + endAtBlock = _endAtBlock; + } + + function setBeneficiary(address to) onlyOwner external { + require(to != 0x0); + beneficiary = to; + } + + function withdraw() onlyOwner softCapReached external { + require(this.balance > 0); + beneficiary.transfer(this.balance); + } + + function contribute(address _address) private stopInEmergency duringPresale { + require(msg.value >= 0.5 ether); // Minimal contribution + + uint256 tokensToIssue; + + if(msg.value >= expertThreshold) { + tokensToIssue = (msg.value / 1 ether).mul(expertTokensPerEth); + } else if(msg.value >= advancedThreshold) { + tokensToIssue = (msg.value / 1 ether).mul(advancedTokensPerEth); + } else { + tokensToIssue = (msg.value / 1 ether).mul(basicTokensPerEth); + } + + totalSupply = totalSupply.add(tokensToIssue); + require(totalSupply <= SUPPLY_LIMIT); + + etherContributions[_address] = etherContributions[_address].add(msg.value); + uint collectedBefore = etherCollected; + etherCollected = etherCollected.add(msg.value); + balanceOf[_address] = balanceOf[_address].add(tokensToIssue); + + NewContribution(_address, tokensToIssue, msg.value); + + if(totalSupply == SUPPLY_LIMIT) { + GoalReached(etherCollected); + } + if(etherCollected >= softCap && collectedBefore < softCap) { + SoftCapReached(etherCollected); + } + } + + function() external payable { + contribute(msg.sender); + } + + function refund() stopInEmergency duringRefund external { + uint tokensToBurn = balanceOf[msg.sender]; + + require(tokensToBurn > 0); // Sender must have tokens + balanceOf[msg.sender] = 0; // Burn + + uint amount = etherContributions[msg.sender]; // User contribution amount + + require(amount > 0); // Amount must be positive -- refund is not processed yet + + etherContributions[msg.sender] = 0; // Clear state + + // Reduce counters + etherCollected = etherCollected.sub(amount); + totalSupply = totalSupply.sub(balanceOf[msg.sender]); + + msg.sender.transfer(amount); // Process refund. In case of error, it will be thrown + + Refunded(msg.sender, amount); + } + + +} diff --git a/contracts/MetaCoin.sol b/contracts/MetaCoin.sol new file mode 100644 index 0000000..fa570e9 --- /dev/null +++ b/contracts/MetaCoin.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.4.4; + +import "./ConvertLib.sol"; + +// This is just a simple example of a coin-like contract. +// It is not standards compatible and cannot be expected to talk to other +// coin/token contracts. If you want to create a standards-compliant +// token, see: https://github.com/ConsenSys/Tokens. Cheers! + +contract MetaCoin { + mapping (address => uint) balances; + + event Transfer(address indexed _from, address indexed _to, uint256 _value); + + function MetaCoin() { + balances[tx.origin] = 10000; + } + + function sendCoin(address receiver, uint amount) returns(bool sufficient) { + if (balances[msg.sender] < amount) return false; + balances[msg.sender] -= amount; + balances[receiver] += amount; + Transfer(msg.sender, receiver, amount); + return true; + } + + function getBalanceInEth(address addr) returns(uint){ + return ConvertLib.convert(getBalance(addr),2); + } + + function getBalance(address addr) returns(uint) { + return balances[addr]; + } +} diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol new file mode 100644 index 0000000..7e7fe8d --- /dev/null +++ b/contracts/Migrations.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.4; + +contract Migrations { + address public owner; + uint public last_completed_migration; + + modifier restricted() { + if (msg.sender == owner) _; + } + + function Migrations() { + owner = msg.sender; + } + + function setCompleted(uint completed) restricted { + last_completed_migration = completed; + } + + function upgrade(address new_address) restricted { + Migrations upgraded = Migrations(new_address); + upgraded.setCompleted(last_completed_migration); + } +} diff --git a/migrations/1_initial_migration.js b/migrations/1_initial_migration.js new file mode 100644 index 0000000..4d5f3f9 --- /dev/null +++ b/migrations/1_initial_migration.js @@ -0,0 +1,5 @@ +var Migrations = artifacts.require("./Migrations.sol"); + +module.exports = function(deployer) { + deployer.deploy(Migrations); +}; diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js new file mode 100644 index 0000000..d1ae65b --- /dev/null +++ b/migrations/2_deploy_contracts.js @@ -0,0 +1,5 @@ +var FluencePreSale = artifacts.require("./FluencePreSale.sol"); + +module.exports = function(deployer) { + deployer.deploy(FluencePreSale, 673000, 674000); +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8834f12 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,649 @@ +{ + "name": "smartcontract", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=" + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=" + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.0.tgz", + "integrity": "sha512-pIU2PJjrPYvYRqVpjXzj76qltO9uBYI7woYAMoxbSefsa+vqAfptjoeevd6bUgwD0mPIO+hv9f7ltvsNreL2PA==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "original-require": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", + "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "requires": { + "glob": "7.1.1" + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "solc": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.13.tgz", + "integrity": "sha1-qly9zOPmrjwZDSD1/fi8iAcC7HU=", + "requires": { + "fs-extra": "0.30.0", + "memorystream": "0.3.1", + "require-from-string": "1.2.1", + "semver": "5.4.1", + "yargs": "4.8.1" + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "requires": { + "has-flag": "1.0.0" + } + }, + "truffle": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/truffle/-/truffle-3.4.7.tgz", + "integrity": "sha512-sAc1dixGDpt38Qq9gqEEIFpXXIIaNKViWlojD9Xv4NBqK/03lxb43M7gcILM4gMpgMdwtTAunG4ZQe7z+HYvJQ==", + "requires": { + "mocha": "3.5.0", + "original-require": "1.0.1", + "solc": "0.4.13" + } + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9dcceb9 --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "name": "smartcontract", + "version": "0.0.0", + "private": true, + "scripts": { + "run": "truffle build" + }, + "dependencies": { + "truffle": "^3.4.7" + } +} diff --git a/test/TestFluencePreSale.sol b/test/TestFluencePreSale.sol new file mode 100644 index 0000000..93e572d --- /dev/null +++ b/test/TestFluencePreSale.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.4.2; + +import "truffle/Assert.sol"; +import "truffle/DeployedAddresses.sol"; +import "../contracts/FluencePreSale.sol"; + +contract TestFluencePreSale { + + uint public initialBalance = 10 ether; + + function testSoftCap() { + FluencePreSale fluence = FluencePreSale(DeployedAddresses.FluencePreSale()); + + uint expected = 1000 ether; + + Assert.equal(fluence.softCap(), expected, "Soft cap must be 1000 ether"); + } + + function testContribute() { + FluencePreSale fluence = new FluencePreSale(0, 100000000000); + + Assert.equal(fluence.owner(), tx.origin, "Owner must be set to sender"); + + fluence.transfer.value(1 ether).gas(210000)(); + + assert(fluence.balanceOf(tx.origin) == 1500); + + Assert.equal(fluence.balanceOf(tx.origin), 1500, "User should get 1500 FPT for 1 eth"); + } + +} diff --git a/test/TestMetacoin.sol b/test/TestMetacoin.sol new file mode 100644 index 0000000..7268664 --- /dev/null +++ b/test/TestMetacoin.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.4.2; + +import "truffle/Assert.sol"; +import "truffle/DeployedAddresses.sol"; +import "../contracts/MetaCoin.sol"; + +contract TestMetacoin { + + function testInitialBalanceUsingDeployedContract() { + MetaCoin meta = new MetaCoin(); + + uint expected = 10000; + + Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially"); + } + + function testInitialBalanceWithNewMetaCoin() { + MetaCoin meta = new MetaCoin(); + + uint expected = 10000; + + Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially"); + } + +} diff --git a/test/metacoin.js b/test/metacoin.js new file mode 100644 index 0000000..c61c093 --- /dev/null +++ b/test/metacoin.js @@ -0,0 +1,63 @@ +var MetaCoin = artifacts.require("./MetaCoin.sol"); + +contract('MetaCoin', function(accounts) { + it("should put 10000 MetaCoin in the first account", function() { + return MetaCoin.deployed().then(function(instance) { + return instance.getBalance.call(accounts[0]); + }).then(function(balance) { + assert.equal(balance.valueOf(), 10000, "10000 wasn't in the first account"); + }); + }); + it("should call a function that depends on a linked library", function() { + var meta; + var metaCoinBalance; + var metaCoinEthBalance; + + return MetaCoin.deployed().then(function(instance) { + meta = instance; + return meta.getBalance.call(accounts[0]); + }).then(function(outCoinBalance) { + metaCoinBalance = outCoinBalance.toNumber(); + return meta.getBalanceInEth.call(accounts[0]); + }).then(function(outCoinBalanceEth) { + metaCoinEthBalance = outCoinBalanceEth.toNumber(); + }).then(function() { + assert.equal(metaCoinEthBalance, 2 * metaCoinBalance, "Library function returned unexpected function, linkage may be broken"); + }); + }); + it("should send coin correctly", function() { + var meta; + + // Get initial balances of first and second account. + var account_one = accounts[0]; + var account_two = accounts[1]; + + var account_one_starting_balance; + var account_two_starting_balance; + var account_one_ending_balance; + var account_two_ending_balance; + + var amount = 10; + + return MetaCoin.deployed().then(function(instance) { + meta = instance; + return meta.getBalance.call(account_one); + }).then(function(balance) { + account_one_starting_balance = balance.toNumber(); + return meta.getBalance.call(account_two); + }).then(function(balance) { + account_two_starting_balance = balance.toNumber(); + return meta.sendCoin(account_two, amount, {from: account_one}); + }).then(function() { + return meta.getBalance.call(account_one); + }).then(function(balance) { + account_one_ending_balance = balance.toNumber(); + return meta.getBalance.call(account_two); + }).then(function(balance) { + account_two_ending_balance = balance.toNumber(); + + assert.equal(account_one_ending_balance, account_one_starting_balance - amount, "Amount wasn't correctly taken from the sender"); + assert.equal(account_two_ending_balance, account_two_starting_balance + amount, "Amount wasn't correctly sent to the receiver"); + }); + }); +}); diff --git a/truffle.js b/truffle.js new file mode 100644 index 0000000..2491c7c --- /dev/null +++ b/truffle.js @@ -0,0 +1,9 @@ +module.exports = { + networks: { + development: { + host: "localhost", + port: 8545, + network_id: "*" // Match any network id + } + } +};