├── .babelrc
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .node-xmlhttprequest-content-32793
├── .solcover.js
├── .vscode
├── launch.json
└── settings.json
├── LICENSE
├── README.md
├── abis
└── tokenSale.txt
├── app
├── index.html
├── javascripts
│ └── app.js
└── stylesheets
│ └── app.css
├── array.json
├── array.txt
├── balances.csv
├── build
└── contracts
│ ├── ApproveAndCallReceiver.json
│ ├── CallFallback.json
│ ├── Controllable.json
│ ├── Controller.json
│ ├── ControllerInterface.json
│ ├── ERC20.json
│ ├── Migrations.json
│ ├── Ownable.json
│ ├── Pausable.json
│ ├── ProofPresaleToken.json
│ ├── ProofPresaleTokenInterface.json
│ ├── ProofToken.json
│ ├── ProofTokenInterface.json
│ ├── SafeMath.json
│ ├── TokenFactory.json
│ ├── TokenFactoryInterface.json
│ └── Tokensale.json
├── config.js
├── contracts
├── ApproveAndCallReceiver.sol
├── Controllable.sol
├── ControllerInterface.sol
├── ERC20.sol
├── Migrations.sol
├── Ownable.sol
├── Pausable.sol
├── ProofPresaleToken.sol
├── ProofPresaleTokenInterface.sol
├── ProofToken.sol
├── ProofTokenInterface.sol
├── SafeMath.sol
├── TokenFactory.sol
├── TokenFactoryInterface.sol
└── TokenSale.sol
├── coverage.json
├── jsdoc.json
├── migrations
├── 1_initial_migration.js
└── 2_deploy_contracts.js
├── other_test
└── crowdsale.js
├── package-lock.json
├── package.json
├── scripts
├── .vscode
│ └── tasks.json
├── addresses.csv
├── balances.csv
├── controlHelpers.js
├── disableTransfers.js
├── enableTransfers.js
├── getPresaleBalances.js
├── helpers.js
├── importBalances.js
├── jsHelpers.js
├── lockBalances.js
├── logEvents.js
├── ownershipHelpers.js
├── pausableHelpers.js
├── testConfig.js
├── tokenHelpers.js
├── tokenSaleHelpers.js
├── transferTokenControl.js
├── transferTokenSaleOwnership.js
├── utils.js
└── watchEvents.js
├── test
├── addresses.csv
├── balances.csv
├── cloneProofToken.js
├── initialState.js
├── ownable.js
├── pausable.js
├── payments.js
├── proofToken.js
└── tokenSale.js
├── truffle.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env"]
3 | }
4 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | tmp/**
2 | build/**
3 | node_modules/**
4 | contracts/**
5 | migrations/1_initial_migration.js
6 | migrations/2_deploy_contracts.js
7 | test/metacoin.js
8 | test/TestMetacoin.sol
9 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": [
4 | "standard"
5 | ],
6 | "plugins": [
7 | "babel"
8 | ],
9 | "rules": {
10 | "key-spacing" : 0,
11 | "jsx-quotes" : [2, "prefer-single"],
12 | "max-len" : [2, 120, 2],
13 | "object-curly-spacing" : [2, "always"],
14 | "no-extend-native": "off"
15 | },
16 | "env": {
17 | "mocha": true,
18 | "node": true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # node xml requests
61 | .node-xmlhttprequest-sync*
62 |
63 |
--------------------------------------------------------------------------------
/.node-xmlhttprequest-content-32793:
--------------------------------------------------------------------------------
1 | {"err":null,"data":{"statusCode":200,"headers":{"access-control-allow-headers":"Origin, X-Requested-With, Content-Type, Accept","access-control-allow-origin":"*","access-control-allow-methods":"*","content-type":"application/json","date":"Sun, 22 Oct 2017 10:10:31 GMT","connection":"close","transfer-encoding":"chunked"},"text":"{\"id\":231,\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x2491df7ecd7c6c79c15119d4bd98b39721be1732dfd198bc9dc729216a46f23a\",\"transactionIndex\":\"0x00\",\"blockHash\":\"0xf50bf77470ea4a15f6d6f8836633d8eaebee618aaf5b6add9e500f6f2c5de9bc\",\"blockNumber\":\"0x0373\",\"gasUsed\":\"0x02bdd5\",\"cumulativeGasUsed\":\"0x02bdd5\",\"contractAddress\":null,\"logs\":[{\"logIndex\":\"0x00\",\"transactionIndex\":\"0x00\",\"transactionHash\":\"0x2491df7ecd7c6c79c15119d4bd98b39721be1732dfd198bc9dc729216a46f23a\",\"blockHash\":\"0xf50bf77470ea4a15f6d6f8836633d8eaebee618aaf5b6add9e500f6f2c5de9bc\",\"blockNumber\":\"0x0373\",\"address\":\"0x718a6b69565c30b3e337790ee685a30fdd1206dd\",\"data\":\"0x000000000000000000000000000000000000000000000000b9882c13c1f31488\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"0x0000000000000000000000006704fbfcd5ef766b287262fa2281c105d57246a6\"],\"type\":\"mined\"},{\"logIndex\":\"0x01\",\"transactionIndex\":\"0x00\",\"transactionHash\":\"0x2491df7ecd7c6c79c15119d4bd98b39721be1732dfd198bc9dc729216a46f23a\",\"blockHash\":\"0xf50bf77470ea4a15f6d6f8836633d8eaebee618aaf5b6add9e500f6f2c5de9bc\",\"blockNumber\":\"0x0373\",\"address\":\"0x555303e243f14c174b687d90e01f5314300c17a7\",\"data\":\"0x0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000b9882c13c1f31488\",\"topics\":[\"0x623b3804fa71d67900d064613da8f94b9617215ee90799290593e1745087ad18\",\"0x0000000000000000000000006704fbfcd5ef766b287262fa2281c105d57246a6\",\"0x0000000000000000000000006704fbfcd5ef766b287262fa2281c105d57246a6\"],\"type\":\"mined\"}]}}"}}
--------------------------------------------------------------------------------
/.solcover.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | skipFiles: ['contracts/TokenSale.sol']
3 | };
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "type": "node",
6 | "request": "attach",
7 | "name": "Attach",
8 | "port": 9229
9 | },
10 | {
11 | "type": "node",
12 | "request": "launch",
13 | "name": "Mocha Tests",
14 | "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
15 | "args": [
16 | "-u",
17 | "tdd",
18 | "--timeout",
19 | "999999",
20 | "--colors",
21 | "${workspaceRoot}/test"
22 | ],
23 | "internalConsoleOptions": "openOnSessionStart",
24 | "runtimeExecutable": "/Users/davidvanisacker/.nvm/versions/node/v8.5.0/bin/node"
25 | },
26 | {
27 | "type": "chrome",
28 | "request": "attach",
29 | "name": "Attach to Chrome",
30 | "port": 9222,
31 | "webRoot": "${workspaceRoot}"
32 | },
33 | {
34 | "type": "node",
35 | "request": "launch",
36 | "name": "Launch Program",
37 | "program": "${file}",
38 | "runtimeExecutable": "/Users/davidvanisacker/.nvm/versions/node/v8.5.0/bin/node"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.enable": false
3 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Proof
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Proof Token Sale Smart Contracts
2 | Public Repository for the proof token sale smart contracts
3 |
4 |
5 |
6 | ## Contracts
7 | The ProofToken and TokenSale contracts are inspired by open-zeppelin standard and audited contracts.
8 |
9 | The Proof Tokens are based on the `StandardToken` and `MintableToken` ERC20 contracts. Additional functionality is heavily inspired by the `MinimeToken` (https://github.com/Giveth/minime/blob/master/contracts/MiniMeToken.sol)
10 |
11 | The TokenSale contract is inspired by the open-zeppelin `Crowdsale` contract with additional functionality mixed in.
12 |
13 |
14 | ## Presale and Initial Token Allocations
15 | 295,297 tokens have already been issued during the presale. These tokens will be imported before the first presale
16 |
17 | ## How to use the tokensale contract
18 | The following contracts are hosted on this repository.
19 | - The tokensale contract
20 | - The Proof token contract
21 | - The token factory contract
22 | - Several other interface contracts
23 |
24 |
25 | ## For the ICO team
26 | There are several prerequisites for using the smart contract.
27 |
28 | ### Contract setup:
29 |
30 | #### 1. Compile and migrate the contracts to the network.
31 | This can be done with the `truffle migrate --network ethereum` command. The contract addresses will successively appear
32 | on the console.
33 | #### 2. Import the presale balances
34 | You can use the 'scripts/importBalances.js' along with the provided csv file describing the presale balances.
35 | This import mechanism differs from the traditional way of importing presale balances via a claim function and makes the process
36 | automatic for presale buyers. The counterpart is that this requires more trust in the ICO team.
37 | Only the controller of the Proof token contract can call this function
38 | #### 3. Lock the presale balances
39 | Calling the `lockPresaleBalances` function ensures that no other presale balances can be imported.
40 | Only the controller of the Proof token contract can call this function
41 | #### 4. Transfer the Proof Token control to the Tokensale contract
42 | Proof tokens can only be created by the controller contract. The control of the proof Token can be given
43 | from the contract creator to the tokensale by calling the `changeControl` function.
44 | #### 5. Transfer the ownership of the Tokensale contract to a custom wallet
45 | It is better not to use the wallet that created the contract and transfer ownership to a wallet shared by several members of the team
46 |
47 |
48 | ### Critical Verifications:
49 |
50 | #### 1. Verify the multisig address
51 | The multisig refers to the wallet to which funds from the tokensale are transferred when a investor sends ether
52 | #### 2. Verify the proof token wallet
53 | The proof wallet receives the proof tokens when upon completion of the tokensale
54 | #### 3. Verify the start date and end date
55 | Token purchase can be made only between the start block and the end block
56 | #### 4. Verify the token the token cap, the cap, and the wei cap
57 | The token cap is the maximum number of tokens that can be issued in ERC20 units (= number of tokens times 10^18)
58 | The cap is the maximum number of tokens that can be issued
59 | #### 5. Verify all the rest
60 |
61 |
62 | - The token sale will start on the date indicated by the `startTime` variable. Alternatively, it is possible to force the starting of the token sale by calling the `forceStart` method. Only the tokensale controller can call this method.
63 |
64 | - By default the Proof tokens are not transferable at the start of the tokensale. The controller of the tokensale can call the `enableTransfers` and `lockTransfers` methods to make token transferables. After the endTime, anybody can make the tokens definitely transferables by calling the `enableTransfers` method. The `lockTransfers` method will fail after the end of the token sale.
65 |
66 | - The token master wallet can be used to send tokens to certain addresses (ex: exchanges) without making transfers available to anyone before the end of the presale. The token sale controller can call the `enableMasterTransfers` and `lockMasterTransfers` to activate/deactivate this option.
67 |
68 |
69 | ### Token Sale Pause
70 |
71 |
72 | - The tokensale can be paused with the `pause` function. In this case, token minting is paused and tokens can not be bought anymore. This does not affect whether tokens are transferable or not.
73 |
74 |
75 | ### Token Sale Finalization:
76 |
77 | The token sale can be finalized in different ways.
78 |
79 | - First if the end block is reached, no more tokens can be issued by the token sale. The rest of the functionality of the tokensale contract however remains available. It is necessary to manually enable transfers through the `enableTransfers` function (can only be called by the owner of the tokensale).
80 |
81 |
82 | - The last and standard way to finalize the token sale is to call the `finalize` function. This function can only be called by the owner of the token sale contract and can only be called when the token sale is paused. This automatically finishes the minting of the proof tokens and enables token transfers
83 |
84 | Step-by-step instructions to finalize the token sale:
85 |
86 | 1. Pause the token sale with the `pause` function
87 | 2. Allocate Proof Tokens with the `allocateProofTokens` function - step 1 needs to be completed
88 | 2. Finalize the token sale with the `finalize` function - step 1 and 2 need to be completed
89 | 3. Optionally, transfer the control of the Proof token to another smart-contract
90 |
91 |
92 | ### Development and Testing Environment Setup
93 |
94 | #### Requirements :
95 | - OSX or Linux (Windows setup is likely possible but not covered in this guide)
96 | - Node (version 8.7.0 required for the testing environment)
97 | - testrpc / geth
98 |
99 | #### Testing Environment Setup :
100 |
101 | - Clone the repository and install dependencies
102 |
103 | ```
104 | git clone https://github.com/ProofSuite/ProofPresaleContract.git
105 | cd ProofPresaleContract
106 | npm install
107 | ```
108 |
109 | - Install the latest version of truffle
110 | ```
111 | npm install -g truffle
112 | ```
113 |
114 | - Compile contracts
115 | ```
116 | truffle compile
117 | ```
118 |
119 | - Initialize testrpc (or geth)
120 |
121 | ```
122 | testrpc
123 | ```
124 |
125 | - Migrate contracts to chosen network
126 |
127 | ```
128 | truffle migrate --network development
129 | ```
130 |
131 | - Make sure you are using the latest version of node
132 |
133 | ```
134 | nvm install 8.7.0
135 | nvm use 8.7.0
136 | ```
137 |
138 |
139 | - Fill in `truffle.js` and `deploy_contracts.js` with appropriate wallet addresses. Unlock the corresponding accounts.
140 |
141 | - Verify all tests are passing
142 |
143 | ```
144 | truffle test
145 | ```
146 |
147 | - You can interact with the contracts via the console
148 |
149 | ```
150 | truffle console
151 | ```
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/abis/tokenSale.txt:
--------------------------------------------------------------------------------
1 | [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"creationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"presaleBalancesLocked","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","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":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_blockNumber","type":"uint256"}],"name":"balanceOfAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"TOKENS_ALLOCATED_TO_PROOF","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"lockPresaleBalances","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newController","type":"address"}],"name":"transferControl","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"parentToken","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_blockNumber","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_amount","type":"uint256"}],"name":"burn","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_snapshotBlock","type":"uint256"},{"name":"_cloneTokenName","type":"string"},{"name":"_cloneTokenSymbol","type":"string"}],"name":"createCloneToken","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"transfersEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"parentSnapShotBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"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"},{"constant":true,"inputs":[],"name":"proofTokenWallet","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"tokenFactory","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addresses","type":"address[]"},{"name":"_balances","type":"uint256[]"},{"name":"_presaleAddress","type":"address"}],"name":"importPresaleBalances","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_transfersEnabled","type":"bool"}],"name":"enableTransfers","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"controller","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"presale","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"_tokenFactory","type":"address"},{"name":"_parentToken","type":"address"},{"name":"_parentSnapShotBlock","type":"uint256"},{"name":"_tokenName","type":"string"},{"name":"_tokenSymbol","type":"string"}],"payable":false,"type":"constructor"},{"payable":true,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_token","type":"address"},{"indexed":true,"name":"_owner","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"ClaimedTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_cloneToken","type":"address"},{"indexed":false,"name":"_snapshotBlock","type":"uint256"}],"name":"NewCloneToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Approval","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"}]
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MetaCoin - Truffle Webpack Demo w/ Frontend
5 |
6 |
7 |
8 |
9 | MetaCoin
10 | Example Truffle Dapp
11 | You have META
12 |
13 |
14 | Send MetaCoin
15 | Amount:
16 | To Address:
17 | Send MetaCoin
18 |
19 |
20 |
21 | Hint: open the browser developer console to view any errors and warnings.
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/javascripts/app.js:
--------------------------------------------------------------------------------
1 | // Import the page's CSS. Webpack will know what to do with it.
2 | import "../stylesheets/app.css";
3 |
4 | // Import libraries we need.
5 | import { default as Web3} from 'web3';
6 | import { default as contract } from 'truffle-contract'
7 |
8 | // Import our contract artifacts and turn them into usable abstractions.
9 | import metacoin_artifacts from '../../build/contracts/MetaCoin.json'
10 |
11 | // MetaCoin is our usable abstraction, which we'll use through the code below.
12 | var MetaCoin = contract(metacoin_artifacts);
13 |
14 | // The following code is simple to show off interacting with your contracts.
15 | // As your needs grow you will likely need to change its form and structure.
16 | // For application bootstrapping, check out window.addEventListener below.
17 | var accounts;
18 | var account;
19 |
20 | window.App = {
21 | start: function() {
22 | var self = this;
23 |
24 | // Bootstrap the MetaCoin abstraction for Use.
25 | MetaCoin.setProvider(web3.currentProvider);
26 |
27 | // Get the initial account balance so it can be displayed.
28 | web3.eth.getAccounts(function(err, accs) {
29 | if (err != null) {
30 | alert("There was an error fetching your accounts.");
31 | return;
32 | }
33 |
34 | if (accs.length == 0) {
35 | alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
36 | return;
37 | }
38 |
39 | accounts = accs;
40 | account = accounts[0];
41 |
42 | self.refreshBalance();
43 | });
44 | },
45 |
46 | setStatus: function(message) {
47 | var status = document.getElementById("status");
48 | status.innerHTML = message;
49 | },
50 |
51 | refreshBalance: function() {
52 | var self = this;
53 |
54 | var meta;
55 | MetaCoin.deployed().then(function(instance) {
56 | meta = instance;
57 | return meta.getBalance.call(account, {from: account});
58 | }).then(function(value) {
59 | var balance_element = document.getElementById("balance");
60 | balance_element.innerHTML = value.valueOf();
61 | }).catch(function(e) {
62 | console.log(e);
63 | self.setStatus("Error getting balance; see log.");
64 | });
65 | },
66 |
67 | sendCoin: function() {
68 | var self = this;
69 |
70 | var amount = parseInt(document.getElementById("amount").value);
71 | var receiver = document.getElementById("receiver").value;
72 |
73 | this.setStatus("Initiating transaction... (please wait)");
74 |
75 | var meta;
76 | MetaCoin.deployed().then(function(instance) {
77 | meta = instance;
78 | return meta.sendCoin(receiver, amount, {from: account});
79 | }).then(function() {
80 | self.setStatus("Transaction complete!");
81 | self.refreshBalance();
82 | }).catch(function(e) {
83 | console.log(e);
84 | self.setStatus("Error sending coin; see log.");
85 | });
86 | }
87 | };
88 |
89 | window.addEventListener('load', function() {
90 | // Checking if Web3 has been injected by the browser (Mist/MetaMask)
91 | if (typeof web3 !== 'undefined') {
92 | console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
93 | // Use Mist/MetaMask's provider
94 | window.web3 = new Web3(web3.currentProvider);
95 | } else {
96 | console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
97 | // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
98 | window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
99 | }
100 |
101 | App.start();
102 | });
103 |
--------------------------------------------------------------------------------
/app/stylesheets/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin-left: 25%;
3 | margin-right: 25%;
4 | margin-top: 10%;
5 | font-family: "Open Sans", sans-serif;
6 | }
7 |
8 | label {
9 | display: inline-block;
10 | width: 100px;
11 | }
12 |
13 | input {
14 | width: 500px;
15 | padding: 5px;
16 | font-size: 16px;
17 | }
18 |
19 | button {
20 | font-size: 16px;
21 | padding: 5px;
22 | }
23 |
24 | h1, h2 {
25 | display: inline-block;
26 | vertical-align: middle;
27 | margin-top: 0px;
28 | margin-bottom: 10px;
29 | }
30 |
31 | h2 {
32 | color: #AAA;
33 | font-size: 32px;
34 | }
35 |
36 | h3 {
37 | font-weight: normal;
38 | color: #AAA;
39 | font-size: 24px;
40 | }
41 |
42 | .black {
43 | color: black;
44 | }
45 |
46 | #balance {
47 | color: black;
48 | }
49 |
50 | .hint {
51 | color: #666;
52 | }
53 |
--------------------------------------------------------------------------------
/array.json:
--------------------------------------------------------------------------------
1 | [202,500,17680,300,294,200,202,438,202,820,454,220,1500,240,400,202,200,202,399,200,210,400,0,800,400,1360,320,815,300,400,202,548,200,800,202,202,200,200,740,230,1000,1460,201,1329,280,202,200,200,600,400,202,200,60,100,140,40,100,203,202,202,200,200,400,200,200,660,202,200,202,200,200,202,200,976,643,200,220,481,212,200,613,105,270,202,200,200,320,200,202,500,900,900,300,220,400,200,65,200,400,200,200,200,200,200,238,200,200,400,209,202,400,1000,0,200,100,100,400,65,75,400,25,40,100,100,800,200,800,202,200,276,280,22,58,300,100,40,1,9,200,200,202,200,500,200,400,202,204,200,200,200,300,200,200,0,40,50,40,200,200,null,40,230,200,200,280,1166,4000,202,200,1740,200,558,200,652,200,240,210,210,210,660,201,200,202,200,798,350,280,200,1000,50,260,202,200,790,220,240,200,212,200,400,580,200,100,100,500,299,490,204]
--------------------------------------------------------------------------------
/array.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ProofSuite/contracts/fda152a7859abe2ab0300ca04bec18f2c9bc0300/array.txt
--------------------------------------------------------------------------------
/build/contracts/ApproveAndCallReceiver.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "ApproveAndCallReceiver",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "from",
9 | "type": "address"
10 | },
11 | {
12 | "name": "_amount",
13 | "type": "uint256"
14 | },
15 | {
16 | "name": "_token",
17 | "type": "address"
18 | },
19 | {
20 | "name": "_data",
21 | "type": "bytes"
22 | }
23 | ],
24 | "name": "receiveApproval",
25 | "outputs": [],
26 | "payable": false,
27 | "type": "function"
28 | }
29 | ],
30 | "unlinked_binary": "0x",
31 | "networks": {},
32 | "schema_version": "0.0.5",
33 | "updated_at": 1509388887463
34 | }
--------------------------------------------------------------------------------
/build/contracts/CallFallback.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "CallFallback",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "from",
9 | "type": "address"
10 | },
11 | {
12 | "name": "_amount",
13 | "type": "uint256"
14 | },
15 | {
16 | "name": "_token",
17 | "type": "address"
18 | },
19 | {
20 | "name": "_data",
21 | "type": "bytes"
22 | }
23 | ],
24 | "name": "receiveApproval",
25 | "outputs": [],
26 | "payable": false,
27 | "type": "function"
28 | }
29 | ],
30 | "unlinked_binary": "0x",
31 | "networks": {},
32 | "schema_version": "0.0.5",
33 | "updated_at": 1508135998543
34 | }
--------------------------------------------------------------------------------
/build/contracts/Controllable.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "Controllable",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "newController",
9 | "type": "address"
10 | }
11 | ],
12 | "name": "transferControl",
13 | "outputs": [],
14 | "payable": false,
15 | "type": "function"
16 | },
17 | {
18 | "constant": true,
19 | "inputs": [],
20 | "name": "controller",
21 | "outputs": [
22 | {
23 | "name": "",
24 | "type": "address"
25 | }
26 | ],
27 | "payable": false,
28 | "type": "function"
29 | },
30 | {
31 | "inputs": [],
32 | "payable": false,
33 | "type": "constructor"
34 | }
35 | ],
36 | "unlinked_binary": "0x6060604052341561000f57600080fd5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101218061003c6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416636d16fa4181146046578063f77c4791146064575b600080fd5b3415605057600080fd5b6062600160a060020a03600435166090565b005b3415606e57600080fd5b607460e6565b604051600160a060020a03909116815260200160405180910390f35b60005433600160a060020a0390811691161460aa57600080fd5b600160a060020a0381161560e1576000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b5b50565b600054600160a060020a0316815600a165627a7a72305820794b7da8dcff39ac0f1fcb0c785fdb02fe29eca2968d825d80b753f9b2b7bd9c0029",
37 | "networks": {},
38 | "schema_version": "0.0.5",
39 | "updated_at": 1509388887462
40 | }
--------------------------------------------------------------------------------
/build/contracts/Controller.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "Controller",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "_from",
9 | "type": "address"
10 | },
11 | {
12 | "name": "_to",
13 | "type": "address"
14 | },
15 | {
16 | "name": "_amount",
17 | "type": "uint256"
18 | }
19 | ],
20 | "name": "onTransfer",
21 | "outputs": [
22 | {
23 | "name": "",
24 | "type": "bool"
25 | }
26 | ],
27 | "payable": false,
28 | "type": "function"
29 | },
30 | {
31 | "constant": false,
32 | "inputs": [
33 | {
34 | "name": "_owner",
35 | "type": "address"
36 | },
37 | {
38 | "name": "_spender",
39 | "type": "address"
40 | },
41 | {
42 | "name": "_amount",
43 | "type": "uint256"
44 | }
45 | ],
46 | "name": "onApprove",
47 | "outputs": [
48 | {
49 | "name": "",
50 | "type": "bool"
51 | }
52 | ],
53 | "payable": false,
54 | "type": "function"
55 | },
56 | {
57 | "constant": false,
58 | "inputs": [
59 | {
60 | "name": "_owner",
61 | "type": "address"
62 | }
63 | ],
64 | "name": "proxyPayment",
65 | "outputs": [
66 | {
67 | "name": "",
68 | "type": "bool"
69 | }
70 | ],
71 | "payable": true,
72 | "type": "function"
73 | }
74 | ],
75 | "unlinked_binary": "0x",
76 | "networks": {},
77 | "schema_version": "0.0.5",
78 | "updated_at": 1506973304207
79 | }
--------------------------------------------------------------------------------
/build/contracts/ControllerInterface.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "ControllerInterface",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "_from",
9 | "type": "address"
10 | },
11 | {
12 | "name": "_to",
13 | "type": "address"
14 | },
15 | {
16 | "name": "_amount",
17 | "type": "uint256"
18 | }
19 | ],
20 | "name": "onTransfer",
21 | "outputs": [
22 | {
23 | "name": "",
24 | "type": "bool"
25 | }
26 | ],
27 | "payable": false,
28 | "type": "function"
29 | },
30 | {
31 | "constant": false,
32 | "inputs": [
33 | {
34 | "name": "_owner",
35 | "type": "address"
36 | },
37 | {
38 | "name": "_spender",
39 | "type": "address"
40 | },
41 | {
42 | "name": "_amount",
43 | "type": "uint256"
44 | }
45 | ],
46 | "name": "onApprove",
47 | "outputs": [
48 | {
49 | "name": "",
50 | "type": "bool"
51 | }
52 | ],
53 | "payable": false,
54 | "type": "function"
55 | },
56 | {
57 | "constant": false,
58 | "inputs": [
59 | {
60 | "name": "_owner",
61 | "type": "address"
62 | }
63 | ],
64 | "name": "proxyPayment",
65 | "outputs": [
66 | {
67 | "name": "",
68 | "type": "bool"
69 | }
70 | ],
71 | "payable": true,
72 | "type": "function"
73 | }
74 | ],
75 | "unlinked_binary": "0x",
76 | "networks": {},
77 | "schema_version": "0.0.5",
78 | "updated_at": 1509388887463
79 | }
--------------------------------------------------------------------------------
/build/contracts/ERC20.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "ERC20",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "_spender",
9 | "type": "address"
10 | },
11 | {
12 | "name": "_amount",
13 | "type": "uint256"
14 | }
15 | ],
16 | "name": "approve",
17 | "outputs": [
18 | {
19 | "name": "",
20 | "type": "bool"
21 | }
22 | ],
23 | "payable": false,
24 | "type": "function"
25 | },
26 | {
27 | "constant": true,
28 | "inputs": [],
29 | "name": "totalSupply",
30 | "outputs": [
31 | {
32 | "name": "",
33 | "type": "uint256"
34 | }
35 | ],
36 | "payable": false,
37 | "type": "function"
38 | },
39 | {
40 | "constant": false,
41 | "inputs": [
42 | {
43 | "name": "_from",
44 | "type": "address"
45 | },
46 | {
47 | "name": "_to",
48 | "type": "address"
49 | },
50 | {
51 | "name": "_amount",
52 | "type": "uint256"
53 | }
54 | ],
55 | "name": "transferFrom",
56 | "outputs": [
57 | {
58 | "name": "",
59 | "type": "bool"
60 | }
61 | ],
62 | "payable": false,
63 | "type": "function"
64 | },
65 | {
66 | "constant": true,
67 | "inputs": [
68 | {
69 | "name": "_owner",
70 | "type": "address"
71 | }
72 | ],
73 | "name": "balanceOf",
74 | "outputs": [
75 | {
76 | "name": "",
77 | "type": "uint256"
78 | }
79 | ],
80 | "payable": false,
81 | "type": "function"
82 | },
83 | {
84 | "constant": false,
85 | "inputs": [
86 | {
87 | "name": "_to",
88 | "type": "address"
89 | },
90 | {
91 | "name": "_value",
92 | "type": "uint256"
93 | }
94 | ],
95 | "name": "transfer",
96 | "outputs": [
97 | {
98 | "name": "",
99 | "type": "bool"
100 | }
101 | ],
102 | "payable": false,
103 | "type": "function"
104 | },
105 | {
106 | "constant": true,
107 | "inputs": [
108 | {
109 | "name": "_owner",
110 | "type": "address"
111 | },
112 | {
113 | "name": "_spender",
114 | "type": "address"
115 | }
116 | ],
117 | "name": "allowance",
118 | "outputs": [
119 | {
120 | "name": "",
121 | "type": "uint256"
122 | }
123 | ],
124 | "payable": false,
125 | "type": "function"
126 | },
127 | {
128 | "anonymous": false,
129 | "inputs": [
130 | {
131 | "indexed": true,
132 | "name": "from",
133 | "type": "address"
134 | },
135 | {
136 | "indexed": true,
137 | "name": "to",
138 | "type": "address"
139 | },
140 | {
141 | "indexed": false,
142 | "name": "value",
143 | "type": "uint256"
144 | }
145 | ],
146 | "name": "Transfer",
147 | "type": "event"
148 | },
149 | {
150 | "anonymous": false,
151 | "inputs": [
152 | {
153 | "indexed": true,
154 | "name": "owner",
155 | "type": "address"
156 | },
157 | {
158 | "indexed": true,
159 | "name": "spender",
160 | "type": "address"
161 | },
162 | {
163 | "indexed": false,
164 | "name": "value",
165 | "type": "uint256"
166 | }
167 | ],
168 | "name": "Approval",
169 | "type": "event"
170 | }
171 | ],
172 | "unlinked_binary": "0x",
173 | "networks": {},
174 | "schema_version": "0.0.5",
175 | "updated_at": 1509273292392
176 | }
--------------------------------------------------------------------------------
/build/contracts/Migrations.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "Migrations",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "new_address",
9 | "type": "address"
10 | }
11 | ],
12 | "name": "upgrade",
13 | "outputs": [],
14 | "payable": false,
15 | "type": "function"
16 | },
17 | {
18 | "constant": true,
19 | "inputs": [],
20 | "name": "last_completed_migration",
21 | "outputs": [
22 | {
23 | "name": "",
24 | "type": "uint256"
25 | }
26 | ],
27 | "payable": false,
28 | "type": "function"
29 | },
30 | {
31 | "constant": true,
32 | "inputs": [],
33 | "name": "owner",
34 | "outputs": [
35 | {
36 | "name": "",
37 | "type": "address"
38 | }
39 | ],
40 | "payable": false,
41 | "type": "function"
42 | },
43 | {
44 | "constant": false,
45 | "inputs": [
46 | {
47 | "name": "completed",
48 | "type": "uint256"
49 | }
50 | ],
51 | "name": "setCompleted",
52 | "outputs": [],
53 | "payable": false,
54 | "type": "function"
55 | },
56 | {
57 | "inputs": [],
58 | "payable": false,
59 | "type": "constructor"
60 | }
61 | ],
62 | "unlinked_binary": "0x6060604052341561000f57600080fd5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101e58061003c6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630900f010811461005e578063445df0ac1461007f5780638da5cb5b146100a4578063fdacd576146100d3575b600080fd5b341561006957600080fd5b61007d600160a060020a03600435166100eb565b005b341561008a57600080fd5b610092610182565b60405190815260200160405180910390f35b34156100af57600080fd5b6100b7610188565b604051600160a060020a03909116815260200160405180910390f35b34156100de57600080fd5b61007d600435610197565b005b6000805433600160a060020a039081169116141561017c5781905080600160a060020a031663fdacd5766001546040517c010000000000000000000000000000000000000000000000000000000063ffffffff84160281526004810191909152602401600060405180830381600087803b151561016757600080fd5b6102c65a03f1151561017857600080fd5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a03908116911614156101b45760018190555b5b5b505600a165627a7a72305820294fd71b3d7846240f6e3c14dcc95a10d2a5e70da6f5614c9a19acf3fadf8dae0029",
63 | "networks": {
64 | "1": {
65 | "events": {},
66 | "links": {},
67 | "address": "0x7ce0b8bbdddcc4e65aa13393e06a6454782cd8fc",
68 | "updated_at": 1509389180349
69 | },
70 | "3": {
71 | "events": {},
72 | "links": {},
73 | "address": "0x647393fcb69eb31b70d59807dd916f9514a639a1",
74 | "updated_at": 1507535880957
75 | },
76 | "4": {
77 | "events": {},
78 | "links": {},
79 | "address": "0x4a8c3f0ccffc9606f6962d6c7e8a1a4459d1f848",
80 | "updated_at": 1508682577039
81 | },
82 | "1504670699258": {
83 | "events": {},
84 | "links": {},
85 | "address": "0xa6421a7f48498cee3aeb6428a8a2dd5faa3ace2f",
86 | "updated_at": 1504672000058
87 | },
88 | "1504691386611": {
89 | "events": {},
90 | "links": {},
91 | "address": "0x5ed8b031ffdc1a1e73adb20edcfcb1fb8c8ed579",
92 | "updated_at": 1504773328278
93 | },
94 | "1504870996916": {
95 | "events": {},
96 | "links": {},
97 | "address": "0x970ccf2182de4797614906db543521e3e8e99bba",
98 | "updated_at": 1504877175473
99 | },
100 | "1505119872715": {
101 | "events": {},
102 | "links": {},
103 | "address": "0x320051bbd4eee344bb86f0a858d03595837463ef",
104 | "updated_at": 1505120395142
105 | },
106 | "1506317398791": {
107 | "events": {},
108 | "links": {},
109 | "address": "0x5bab00b1582b170dbae7557586a29ba9eea6f55b",
110 | "updated_at": 1506327378631
111 | },
112 | "1506498226769": {
113 | "events": {},
114 | "links": {},
115 | "address": "0x0f5ea0a652e851678ebf77b69484bfcd31f9459b",
116 | "updated_at": 1506498253854
117 | },
118 | "1506524752656": {
119 | "events": {},
120 | "links": {},
121 | "address": "0x0f5ea0a652e851678ebf77b69484bfcd31f9459b",
122 | "updated_at": 1506524829933
123 | },
124 | "1506969503782": {
125 | "events": {},
126 | "links": {},
127 | "address": "0x28b291e74bce603004b52921ec9ad3ddb6f85e44",
128 | "updated_at": 1506974436162
129 | },
130 | "1507200004236": {
131 | "events": {},
132 | "links": {},
133 | "address": "0x46e082904569c60d736017c64ff703ae68da11de",
134 | "updated_at": 1507518432707
135 | },
136 | "1508136021086": {
137 | "events": {},
138 | "links": {},
139 | "address": "0x162a36c9821eadecff9669a3940b7f72d055cd1c",
140 | "updated_at": 1508137979261
141 | },
142 | "1508171544663": {
143 | "events": {},
144 | "links": {},
145 | "address": "0x0f5ea0a652e851678ebf77b69484bfcd31f9459b",
146 | "updated_at": 1508171555409
147 | },
148 | "1508214325595": {
149 | "events": {},
150 | "links": {},
151 | "address": "0x7ef88a3901494435700ccc4c7615903b43ec2dbc",
152 | "updated_at": 1508216404737
153 | },
154 | "1508669583748": {
155 | "events": {},
156 | "links": {},
157 | "address": "0xe02779c7bc8bef5fe10da107150167b505eb045e",
158 | "updated_at": 1508691293374
159 | }
160 | },
161 | "schema_version": "0.0.5",
162 | "updated_at": 1509389180349
163 | }
--------------------------------------------------------------------------------
/build/contracts/Ownable.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "Ownable",
3 | "abi": [
4 | {
5 | "constant": true,
6 | "inputs": [],
7 | "name": "owner",
8 | "outputs": [
9 | {
10 | "name": "",
11 | "type": "address"
12 | }
13 | ],
14 | "payable": false,
15 | "type": "function"
16 | },
17 | {
18 | "constant": false,
19 | "inputs": [
20 | {
21 | "name": "newOwner",
22 | "type": "address"
23 | }
24 | ],
25 | "name": "transferOwnership",
26 | "outputs": [],
27 | "payable": false,
28 | "type": "function"
29 | },
30 | {
31 | "inputs": [],
32 | "payable": false,
33 | "type": "constructor"
34 | }
35 | ],
36 | "unlinked_binary": "0x6060604052341561000f57600080fd5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101218061003c6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416638da5cb5b81146046578063f2fde38b146072575b600080fd5b3415605057600080fd5b60566090565b604051600160a060020a03909116815260200160405180910390f35b3415607c57600080fd5b608e600160a060020a0360043516609f565b005b600054600160a060020a031681565b60005433600160a060020a0390811691161460b957600080fd5b600160a060020a0381161560f0576000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b5b505600a165627a7a7230582081bc94352517967f296b92fd8dc37701cd7d5e3a103643caea0f7a25a8c581e90029",
37 | "networks": {},
38 | "schema_version": "0.0.5",
39 | "updated_at": 1509388887463
40 | }
--------------------------------------------------------------------------------
/build/contracts/Pausable.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "Pausable",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [],
7 | "name": "unpause",
8 | "outputs": [
9 | {
10 | "name": "",
11 | "type": "bool"
12 | }
13 | ],
14 | "payable": false,
15 | "type": "function"
16 | },
17 | {
18 | "constant": true,
19 | "inputs": [],
20 | "name": "paused",
21 | "outputs": [
22 | {
23 | "name": "",
24 | "type": "bool"
25 | }
26 | ],
27 | "payable": false,
28 | "type": "function"
29 | },
30 | {
31 | "constant": false,
32 | "inputs": [],
33 | "name": "pause",
34 | "outputs": [
35 | {
36 | "name": "",
37 | "type": "bool"
38 | }
39 | ],
40 | "payable": false,
41 | "type": "function"
42 | },
43 | {
44 | "constant": true,
45 | "inputs": [],
46 | "name": "owner",
47 | "outputs": [
48 | {
49 | "name": "",
50 | "type": "address"
51 | }
52 | ],
53 | "payable": false,
54 | "type": "function"
55 | },
56 | {
57 | "constant": false,
58 | "inputs": [
59 | {
60 | "name": "newOwner",
61 | "type": "address"
62 | }
63 | ],
64 | "name": "transferOwnership",
65 | "outputs": [],
66 | "payable": false,
67 | "type": "function"
68 | },
69 | {
70 | "inputs": [],
71 | "payable": false,
72 | "type": "constructor"
73 | },
74 | {
75 | "anonymous": false,
76 | "inputs": [],
77 | "name": "Pause",
78 | "type": "event"
79 | },
80 | {
81 | "anonymous": false,
82 | "inputs": [],
83 | "name": "Unpause",
84 | "type": "event"
85 | }
86 | ],
87 | "unlinked_binary": "0x60606040526000805460a060020a60ff0219169055341561001f57600080fd5b5b5b60008054600160a060020a03191633600160a060020a03161790555b5b5b6102e48061004e6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633f4ba83a81146100695780635c975abb146100905780638456cb59146100b75780638da5cb5b146100de578063f2fde38b1461010d575b600080fd5b341561007457600080fd5b61007c61012e565b604051901515815260200160405180910390f35b341561009b57600080fd5b61007c6101b5565b604051901515815260200160405180910390f35b34156100c257600080fd5b61007c6101c5565b604051901515815260200160405180910390f35b34156100e957600080fd5b6100f1610251565b604051600160a060020a03909116815260200160405180910390f35b341561011857600080fd5b61012c600160a060020a0360043516610260565b005b6000805433600160a060020a0390811691161461014a57600080fd5b60005460a060020a900460ff16151561016257600080fd5b6000805474ff0000000000000000000000000000000000000000191690557f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3360405160405180910390a15060015b5b5b90565b60005460a060020a900460ff1681565b6000805433600160a060020a039081169116146101e157600080fd5b60005460a060020a900460ff16156101f857600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1790557f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62560405160405180910390a15060015b5b5b90565b600054600160a060020a031681565b60005433600160a060020a0390811691161461027b57600080fd5b600160a060020a038116156102b3576000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b5b505600a165627a7a723058209c60b6313881749c62989ee94a7cdb4cecbadca33f61d295fb363e29bd01d6c00029",
88 | "networks": {},
89 | "schema_version": "0.0.5",
90 | "updated_at": 1509388887465
91 | }
--------------------------------------------------------------------------------
/build/contracts/ProofPresaleTokenInterface.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "ProofPresaleTokenInterface",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "_spender",
9 | "type": "address"
10 | },
11 | {
12 | "name": "_value",
13 | "type": "uint256"
14 | }
15 | ],
16 | "name": "approve",
17 | "outputs": [
18 | {
19 | "name": "",
20 | "type": "bool"
21 | }
22 | ],
23 | "payable": false,
24 | "type": "function"
25 | },
26 | {
27 | "constant": true,
28 | "inputs": [],
29 | "name": "totalSupply",
30 | "outputs": [
31 | {
32 | "name": "",
33 | "type": "uint256"
34 | }
35 | ],
36 | "payable": false,
37 | "type": "function"
38 | },
39 | {
40 | "constant": false,
41 | "inputs": [
42 | {
43 | "name": "_from",
44 | "type": "address"
45 | },
46 | {
47 | "name": "_to",
48 | "type": "address"
49 | },
50 | {
51 | "name": "_value",
52 | "type": "uint256"
53 | }
54 | ],
55 | "name": "transferFrom",
56 | "outputs": [
57 | {
58 | "name": "",
59 | "type": "bool"
60 | }
61 | ],
62 | "payable": false,
63 | "type": "function"
64 | },
65 | {
66 | "constant": false,
67 | "inputs": [
68 | {
69 | "name": "_to",
70 | "type": "address"
71 | },
72 | {
73 | "name": "_amount",
74 | "type": "uint256"
75 | }
76 | ],
77 | "name": "mint",
78 | "outputs": [
79 | {
80 | "name": "",
81 | "type": "bool"
82 | }
83 | ],
84 | "payable": false,
85 | "type": "function"
86 | },
87 | {
88 | "constant": true,
89 | "inputs": [
90 | {
91 | "name": "_owner",
92 | "type": "address"
93 | }
94 | ],
95 | "name": "balanceOf",
96 | "outputs": [
97 | {
98 | "name": "",
99 | "type": "uint256"
100 | }
101 | ],
102 | "payable": false,
103 | "type": "function"
104 | },
105 | {
106 | "constant": false,
107 | "inputs": [],
108 | "name": "finishMinting",
109 | "outputs": [
110 | {
111 | "name": "",
112 | "type": "bool"
113 | }
114 | ],
115 | "payable": false,
116 | "type": "function"
117 | },
118 | {
119 | "constant": false,
120 | "inputs": [
121 | {
122 | "name": "_to",
123 | "type": "address"
124 | },
125 | {
126 | "name": "_value",
127 | "type": "uint256"
128 | }
129 | ],
130 | "name": "transfer",
131 | "outputs": [
132 | {
133 | "name": "",
134 | "type": "bool"
135 | }
136 | ],
137 | "payable": false,
138 | "type": "function"
139 | },
140 | {
141 | "constant": true,
142 | "inputs": [
143 | {
144 | "name": "_owner",
145 | "type": "address"
146 | },
147 | {
148 | "name": "_spender",
149 | "type": "address"
150 | }
151 | ],
152 | "name": "allowance",
153 | "outputs": [
154 | {
155 | "name": "",
156 | "type": "uint256"
157 | }
158 | ],
159 | "payable": false,
160 | "type": "function"
161 | }
162 | ],
163 | "unlinked_binary": "0x",
164 | "networks": {},
165 | "schema_version": "0.0.5",
166 | "updated_at": 1509273292393
167 | }
--------------------------------------------------------------------------------
/build/contracts/ProofTokenInterface.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "ProofTokenInterface",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "_spender",
9 | "type": "address"
10 | },
11 | {
12 | "name": "_amount",
13 | "type": "uint256"
14 | }
15 | ],
16 | "name": "approve",
17 | "outputs": [
18 | {
19 | "name": "success",
20 | "type": "bool"
21 | }
22 | ],
23 | "payable": false,
24 | "type": "function"
25 | },
26 | {
27 | "constant": true,
28 | "inputs": [],
29 | "name": "totalSupply",
30 | "outputs": [
31 | {
32 | "name": "",
33 | "type": "uint256"
34 | }
35 | ],
36 | "payable": false,
37 | "type": "function"
38 | },
39 | {
40 | "constant": false,
41 | "inputs": [
42 | {
43 | "name": "_from",
44 | "type": "address"
45 | },
46 | {
47 | "name": "_to",
48 | "type": "address"
49 | },
50 | {
51 | "name": "_amount",
52 | "type": "uint256"
53 | }
54 | ],
55 | "name": "transferFrom",
56 | "outputs": [
57 | {
58 | "name": "success",
59 | "type": "bool"
60 | }
61 | ],
62 | "payable": false,
63 | "type": "function"
64 | },
65 | {
66 | "constant": false,
67 | "inputs": [
68 | {
69 | "name": "_owner",
70 | "type": "address"
71 | },
72 | {
73 | "name": "_amount",
74 | "type": "uint256"
75 | }
76 | ],
77 | "name": "mint",
78 | "outputs": [
79 | {
80 | "name": "",
81 | "type": "bool"
82 | }
83 | ],
84 | "payable": false,
85 | "type": "function"
86 | },
87 | {
88 | "constant": true,
89 | "inputs": [
90 | {
91 | "name": "_owner",
92 | "type": "address"
93 | },
94 | {
95 | "name": "_blockNumber",
96 | "type": "uint256"
97 | }
98 | ],
99 | "name": "balanceOfAt",
100 | "outputs": [
101 | {
102 | "name": "",
103 | "type": "uint256"
104 | }
105 | ],
106 | "payable": false,
107 | "type": "function"
108 | },
109 | {
110 | "constant": false,
111 | "inputs": [],
112 | "name": "lockPresaleBalances",
113 | "outputs": [
114 | {
115 | "name": "",
116 | "type": "bool"
117 | }
118 | ],
119 | "payable": false,
120 | "type": "function"
121 | },
122 | {
123 | "constant": false,
124 | "inputs": [
125 | {
126 | "name": "newController",
127 | "type": "address"
128 | }
129 | ],
130 | "name": "transferControl",
131 | "outputs": [],
132 | "payable": false,
133 | "type": "function"
134 | },
135 | {
136 | "constant": true,
137 | "inputs": [
138 | {
139 | "name": "_owner",
140 | "type": "address"
141 | }
142 | ],
143 | "name": "balanceOf",
144 | "outputs": [
145 | {
146 | "name": "balance",
147 | "type": "uint256"
148 | }
149 | ],
150 | "payable": false,
151 | "type": "function"
152 | },
153 | {
154 | "constant": false,
155 | "inputs": [],
156 | "name": "finishMinting",
157 | "outputs": [
158 | {
159 | "name": "",
160 | "type": "bool"
161 | }
162 | ],
163 | "payable": false,
164 | "type": "function"
165 | },
166 | {
167 | "constant": true,
168 | "inputs": [
169 | {
170 | "name": "_blockNumber",
171 | "type": "uint256"
172 | }
173 | ],
174 | "name": "totalSupplyAt",
175 | "outputs": [
176 | {
177 | "name": "",
178 | "type": "uint256"
179 | }
180 | ],
181 | "payable": false,
182 | "type": "function"
183 | },
184 | {
185 | "constant": false,
186 | "inputs": [
187 | {
188 | "name": "_snapshotBlock",
189 | "type": "uint256"
190 | },
191 | {
192 | "name": "_cloneTokenName",
193 | "type": "string"
194 | },
195 | {
196 | "name": "_cloneTokenSymbol",
197 | "type": "string"
198 | }
199 | ],
200 | "name": "createCloneToken",
201 | "outputs": [
202 | {
203 | "name": "",
204 | "type": "address"
205 | }
206 | ],
207 | "payable": false,
208 | "type": "function"
209 | },
210 | {
211 | "constant": false,
212 | "inputs": [
213 | {
214 | "name": "_to",
215 | "type": "address"
216 | },
217 | {
218 | "name": "_amount",
219 | "type": "uint256"
220 | }
221 | ],
222 | "name": "transfer",
223 | "outputs": [
224 | {
225 | "name": "success",
226 | "type": "bool"
227 | }
228 | ],
229 | "payable": false,
230 | "type": "function"
231 | },
232 | {
233 | "constant": false,
234 | "inputs": [
235 | {
236 | "name": "_value",
237 | "type": "bool"
238 | }
239 | ],
240 | "name": "enableMasterTransfers",
241 | "outputs": [],
242 | "payable": false,
243 | "type": "function"
244 | },
245 | {
246 | "constant": false,
247 | "inputs": [
248 | {
249 | "name": "_spender",
250 | "type": "address"
251 | },
252 | {
253 | "name": "_amount",
254 | "type": "uint256"
255 | },
256 | {
257 | "name": "_extraData",
258 | "type": "bytes"
259 | }
260 | ],
261 | "name": "approveAndCall",
262 | "outputs": [
263 | {
264 | "name": "success",
265 | "type": "bool"
266 | }
267 | ],
268 | "payable": false,
269 | "type": "function"
270 | },
271 | {
272 | "constant": true,
273 | "inputs": [
274 | {
275 | "name": "_owner",
276 | "type": "address"
277 | },
278 | {
279 | "name": "_spender",
280 | "type": "address"
281 | }
282 | ],
283 | "name": "allowance",
284 | "outputs": [
285 | {
286 | "name": "remaining",
287 | "type": "uint256"
288 | }
289 | ],
290 | "payable": false,
291 | "type": "function"
292 | },
293 | {
294 | "constant": false,
295 | "inputs": [
296 | {
297 | "name": "_addresses",
298 | "type": "address[]"
299 | },
300 | {
301 | "name": "_balances",
302 | "type": "uint256[]"
303 | },
304 | {
305 | "name": "_presaleAddress",
306 | "type": "address"
307 | }
308 | ],
309 | "name": "importPresaleBalances",
310 | "outputs": [
311 | {
312 | "name": "",
313 | "type": "bool"
314 | }
315 | ],
316 | "payable": false,
317 | "type": "function"
318 | },
319 | {
320 | "constant": false,
321 | "inputs": [
322 | {
323 | "name": "_value",
324 | "type": "bool"
325 | }
326 | ],
327 | "name": "enableTransfers",
328 | "outputs": [],
329 | "payable": false,
330 | "type": "function"
331 | },
332 | {
333 | "constant": true,
334 | "inputs": [],
335 | "name": "controller",
336 | "outputs": [
337 | {
338 | "name": "",
339 | "type": "address"
340 | }
341 | ],
342 | "payable": false,
343 | "type": "function"
344 | },
345 | {
346 | "anonymous": false,
347 | "inputs": [
348 | {
349 | "indexed": true,
350 | "name": "to",
351 | "type": "address"
352 | },
353 | {
354 | "indexed": false,
355 | "name": "amount",
356 | "type": "uint256"
357 | }
358 | ],
359 | "name": "Mint",
360 | "type": "event"
361 | },
362 | {
363 | "anonymous": false,
364 | "inputs": [],
365 | "name": "MintFinished",
366 | "type": "event"
367 | },
368 | {
369 | "anonymous": false,
370 | "inputs": [
371 | {
372 | "indexed": true,
373 | "name": "_token",
374 | "type": "address"
375 | },
376 | {
377 | "indexed": true,
378 | "name": "_owner",
379 | "type": "address"
380 | },
381 | {
382 | "indexed": false,
383 | "name": "_amount",
384 | "type": "uint256"
385 | }
386 | ],
387 | "name": "ClaimedTokens",
388 | "type": "event"
389 | },
390 | {
391 | "anonymous": false,
392 | "inputs": [
393 | {
394 | "indexed": true,
395 | "name": "_cloneToken",
396 | "type": "address"
397 | },
398 | {
399 | "indexed": false,
400 | "name": "_snapshotBlock",
401 | "type": "uint256"
402 | }
403 | ],
404 | "name": "NewCloneToken",
405 | "type": "event"
406 | },
407 | {
408 | "anonymous": false,
409 | "inputs": [
410 | {
411 | "indexed": true,
412 | "name": "_owner",
413 | "type": "address"
414 | },
415 | {
416 | "indexed": true,
417 | "name": "_spender",
418 | "type": "address"
419 | },
420 | {
421 | "indexed": false,
422 | "name": "_amount",
423 | "type": "uint256"
424 | }
425 | ],
426 | "name": "Approval",
427 | "type": "event"
428 | },
429 | {
430 | "anonymous": false,
431 | "inputs": [
432 | {
433 | "indexed": true,
434 | "name": "from",
435 | "type": "address"
436 | },
437 | {
438 | "indexed": true,
439 | "name": "to",
440 | "type": "address"
441 | },
442 | {
443 | "indexed": false,
444 | "name": "value",
445 | "type": "uint256"
446 | }
447 | ],
448 | "name": "Transfer",
449 | "type": "event"
450 | }
451 | ],
452 | "unlinked_binary": "0x",
453 | "networks": {},
454 | "schema_version": "0.0.5",
455 | "updated_at": 1509388887465
456 | }
--------------------------------------------------------------------------------
/build/contracts/SafeMath.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "SafeMath",
3 | "abi": [],
4 | "unlinked_binary": "0x60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00a165627a7a7230582061508761e8d7a0b0542f19eb06cf37abb78bd35c2fdbb50ad3b3fa9bf427c0e80029",
5 | "networks": {},
6 | "schema_version": "0.0.5",
7 | "updated_at": 1509388887465
8 | }
--------------------------------------------------------------------------------
/build/contracts/TokenFactoryInterface.json:
--------------------------------------------------------------------------------
1 | {
2 | "contract_name": "TokenFactoryInterface",
3 | "abi": [
4 | {
5 | "constant": false,
6 | "inputs": [
7 | {
8 | "name": "_parentToken",
9 | "type": "address"
10 | },
11 | {
12 | "name": "_snapshotBlock",
13 | "type": "uint256"
14 | },
15 | {
16 | "name": "_tokenName",
17 | "type": "string"
18 | },
19 | {
20 | "name": "_tokenSymbol",
21 | "type": "string"
22 | }
23 | ],
24 | "name": "createCloneToken",
25 | "outputs": [
26 | {
27 | "name": "newToken",
28 | "type": "address"
29 | }
30 | ],
31 | "payable": false,
32 | "type": "function"
33 | }
34 | ],
35 | "unlinked_binary": "0x",
36 | "networks": {},
37 | "schema_version": "0.0.5",
38 | "updated_at": 1509388887466
39 | }
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | let config = {
2 | infura: {
3 | ethereum: 'https://mainnet.infura.io/Oi27hEUIuGqMsrYGpI7e',
4 | ropsten: 'https://ropsten.infura.io/Oi27hEUIuGqMsrYGpI7e',
5 | rinkeby: 'https://rinkeby.infura.io/Oi27hEUIuGqMsrYGpI7e',
6 | kovan: 'https://kovan.infura.io/Oi27hEUIuGqMsrYGpI7e'
7 | },
8 | constants: {
9 | DEFAULT_GAS: 2 * 10 ** 6,
10 | MAX_GAS: 4.7 * 10 ** 6,
11 | DEFAULT_LOW_GAS_PRICE: 0.1 * 10 ** 9,
12 | DEFAULT_GAS_PRICE: 1 * 10 ** 9,
13 | DEFAULT_HIGH_GAS_PRICE: 5 * 10 ** 9,
14 | TOKENS_ALLOCATED_TO_PROOF: 1181031 * (10 ** 18),
15 | DECIMALS_POINTS: 10 ** 18,
16 | TOKEN_UNITS: 10 ** 18,
17 | START_TIMESTAMP: 1509541200,
18 | END_TIMESTAMP: 1512133200,
19 | },
20 | addresses: {
21 | development: {
22 | WALLET_ADDRESS: '0x6704fbfcd5ef766b287262fa2281c105d57246a6',
23 | TOKEN_WALLET_ADDRESS: '0x6704fbfcd5ef766b287262fa2281c105d57246a6'
24 | },
25 | rinkeby: {
26 | WALLET_ADDRESS: '0x9fbdaac5faf6711f38ab26541b7c0d72cb2c0e11',
27 | TOKEN_WALLET_ADDRESS: '0x9fbdaac5faf6711f38ab26541b7c0d72cb2c0e11'
28 | },
29 | ropsten: {
30 | WALLET_ADDRESS: '',
31 | TOKEN_WALLET_ADDRESS: ''
32 | },
33 | ethereum: {
34 | WALLET_ADDRESS: '0x11e3de1bda2650fa6bc74e7cea6a39559e59b103',
35 | TOKEN_WALLET_ADDRESS: '0x11e3de1bda2650fa6bc74e7cea6a39559e59b103',
36 | PRESALE_TOKEN: '0x2469f31A34FCaAc0debf73806cE39B2388874B13'
37 | }
38 | }
39 | }
40 |
41 | module.exports = config
--------------------------------------------------------------------------------
/contracts/ApproveAndCallReceiver.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | contract ApproveAndCallReceiver {
4 | function receiveApproval(address from, uint256 _amount, address _token, bytes _data) public;
5 | }
--------------------------------------------------------------------------------
/contracts/Controllable.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 |
4 | /**
5 | * @title Controllable
6 | * @dev The Controllable contract has an controller address, and provides basic authorization control
7 | * functions, this simplifies the implementation of "user permissions".
8 | */
9 | contract Controllable {
10 | address public controller;
11 |
12 |
13 | /**
14 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender account.
15 | */
16 | function Controllable() public {
17 | controller = msg.sender;
18 | }
19 |
20 | /**
21 | * @dev Throws if called by any account other than the owner.
22 | */
23 | modifier onlyController() {
24 | require(msg.sender == controller);
25 | _;
26 | }
27 |
28 | /**
29 | * @dev Allows the current owner to transfer control of the contract to a newOwner.
30 | * @param newController The address to transfer ownership to.
31 | */
32 | function transferControl(address newController) public onlyController {
33 | if (newController != address(0)) {
34 | controller = newController;
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/contracts/ControllerInterface.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | /// @dev The token controller contract must implement these functions
4 | contract ControllerInterface {
5 |
6 | function proxyPayment(address _owner) public payable returns(bool);
7 | function onTransfer(address _from, address _to, uint _amount) public returns(bool);
8 | function onApprove(address _owner, address _spender, uint _amount) public returns(bool);
9 | }
--------------------------------------------------------------------------------
/contracts/ERC20.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | /**
4 | * @title ERC20 interface
5 | * @dev see https://github.com/ethereum/EIPs/issues/20
6 | */
7 | contract ERC20 {
8 |
9 | uint256 public totalSupply;
10 |
11 | function balanceOf(address _owner) constant returns (uint256);
12 | function transfer(address _to, uint256 _value) returns (bool);
13 | function transferFrom(address _from, address _to, uint256 _amount) returns (bool);
14 | function approve(address _spender, uint256 _amount) returns (bool);
15 | function allowance(address _owner, address _spender) constant returns (uint256);
16 |
17 | event Transfer(address indexed from, address indexed to, uint256 value);
18 | event Approval(address indexed owner, address indexed spender, uint256 value);
19 |
20 | }
--------------------------------------------------------------------------------
/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | contract Migrations {
4 | address public owner;
5 | uint public last_completed_migration;
6 |
7 | modifier restricted() {
8 | if (msg.sender == owner) _;
9 | }
10 |
11 | function Migrations() {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/contracts/Ownable.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 |
4 | /**
5 | * @title Ownable
6 | * @dev The Ownable contract has an owner address, and provides basic authorization control
7 | * functions, this simplifies the implementation of "user permissions".
8 | */
9 | contract Ownable {
10 | address public owner;
11 |
12 |
13 | /**
14 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender account.
15 | */
16 | function Ownable() public {
17 | owner = msg.sender;
18 | }
19 |
20 | /**
21 | * @dev Throws if called by any account other than the owner.
22 | */
23 | modifier onlyOwner() {
24 | require(msg.sender == owner);
25 | _;
26 | }
27 |
28 | /**
29 | * @dev Allows the current owner to transfer control of the contract to a newOwner.
30 | * @param newOwner The address to transfer ownership to.
31 | */
32 | function transferOwnership(address newOwner) public onlyOwner {
33 | if (newOwner != address(0)) {
34 | owner = newOwner;
35 | }
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/contracts/Pausable.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 |
4 | import "./Ownable.sol";
5 |
6 |
7 | /**
8 | * @title Pausable
9 | * @dev Base contract which allows children to implement an emergency stop mechanism.
10 | */
11 | contract Pausable is Ownable {
12 | event Pause();
13 | event Unpause();
14 |
15 | bool public paused = false;
16 |
17 | function Pausable() public {}
18 |
19 | /**
20 | * @dev modifier to allow actions only when the contract IS paused
21 | */
22 | modifier whenNotPaused() {
23 | require(!paused);
24 | _;
25 | }
26 |
27 | /**
28 | * @dev modifier to allow actions only when the contract IS NOT paused
29 | */
30 | modifier whenPaused {
31 | require(paused);
32 | _;
33 | }
34 |
35 | /**
36 | * @dev called by the owner to pause, triggers stopped state
37 | */
38 | function pause() public onlyOwner whenNotPaused returns (bool) {
39 | paused = true;
40 | Pause();
41 | return true;
42 | }
43 |
44 | /**
45 | * @dev called by the owner to unpause, returns to normal state
46 | */
47 | function unpause() public onlyOwner whenPaused returns (bool) {
48 | paused = false;
49 | Unpause();
50 | return true;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/contracts/ProofPresaleToken.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | import './SafeMath.sol';
4 | import './ERC20.sol';
5 | import './Controllable.sol';
6 |
7 | /**
8 | * @title ProofPresaleToken (PROOFP)
9 | * Standard Mintable ERC20 Token
10 | * https://github.com/ethereum/EIPs/issues/20
11 | * Based on code by FirstBlood:
12 | * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
13 | */
14 |
15 | contract ProofPresaleToken is ERC20, Controllable {
16 |
17 | using SafeMath for uint256;
18 |
19 | uint256 public totalSupply;
20 |
21 | mapping(address => uint) balances;
22 | mapping (address => mapping (address => uint)) allowed;
23 |
24 | string public constant name = "Proof Presale Token";
25 | string public constant symbol = "PPT";
26 | uint8 public constant decimals = 18;
27 | bool public mintingFinished = false;
28 |
29 | event Mint(address indexed to, uint256 amount);
30 | event MintFinished();
31 |
32 | function ProofPresaleToken() {}
33 |
34 | function() payable {
35 | revert();
36 | }
37 |
38 | function balanceOf(address _owner) constant returns (uint256) {
39 | return balances[_owner];
40 | }
41 |
42 | function transfer(address _to, uint _value) returns (bool) {
43 |
44 | balances[msg.sender] = balances[msg.sender].sub(_value);
45 | balances[_to] = balances[_to].add(_value);
46 |
47 | Transfer(msg.sender, _to, _value);
48 | return true;
49 | }
50 |
51 | function transferFrom(address _from, address _to, uint _value) returns (bool) {
52 | var _allowance = allowed[_from][msg.sender];
53 |
54 | balances[_to] = balances[_to].add(_value);
55 | balances[_from] = balances[_from].sub(_value);
56 | allowed[_from][msg.sender] = _allowance.sub(_value);
57 |
58 | Transfer(_from, _to, _value);
59 | return true;
60 | }
61 |
62 | function approve(address _spender, uint _value) returns (bool) {
63 | allowed[msg.sender][_spender] = _value;
64 | Approval(msg.sender, _spender, _value);
65 | return true;
66 | }
67 |
68 | function allowance(address _owner, address _spender) constant returns (uint256) {
69 | return allowed[_owner][_spender];
70 | }
71 |
72 |
73 | modifier canMint() {
74 | require(!mintingFinished);
75 | _;
76 | }
77 |
78 | function mint(address _to, uint256 _amount) onlyController canMint returns (bool) {
79 | totalSupply = totalSupply.add(_amount);
80 | balances[_to] = balances[_to].add(_amount);
81 | Mint(_to, _amount);
82 | return true;
83 | }
84 |
85 | function finishMinting() onlyController returns (bool) {
86 | mintingFinished = true;
87 | MintFinished();
88 | return true;
89 | }
90 |
91 |
92 | }
--------------------------------------------------------------------------------
/contracts/ProofPresaleTokenInterface.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | /**
4 | * @title ProofPresaleToken (PROOFP)
5 | * Standard Mintable ERC20 Token
6 | * https://github.com/ethereum/EIPs/issues/20
7 | * Based on code by FirstBlood:
8 | * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
9 | */
10 |
11 | contract ProofPresaleTokenInterface {
12 |
13 | uint256 public totalSupply;
14 |
15 | function balanceOf(address _owner) constant returns (uint256);
16 | function transfer(address _to, uint _value) returns (bool);
17 | function transferFrom(address _from, address _to, uint _value) returns (bool);
18 | function approve(address _spender, uint _value) returns (bool);
19 | function allowance(address _owner, address _spender) constant returns (uint256);
20 | function mint(address _to, uint256 _amount) returns (bool);
21 | function finishMinting() returns (bool);
22 |
23 | }
--------------------------------------------------------------------------------
/contracts/ProofTokenInterface.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | import './Controllable.sol';
4 |
5 | /**
6 | * @title ProofToken (PRFT)
7 | * Standard Mintable ERC20 Token
8 | * https://github.com/ethereum/EIPs/issues/20
9 | * Based on code by FirstBlood:
10 | * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
11 | */
12 | contract ProofTokenInterface is Controllable {
13 |
14 | event Mint(address indexed to, uint256 amount);
15 | event MintFinished();
16 | event ClaimedTokens(address indexed _token, address indexed _owner, uint _amount);
17 | event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock);
18 | event Approval(address indexed _owner, address indexed _spender, uint256 _amount);
19 | event Transfer(address indexed from, address indexed to, uint256 value);
20 |
21 | function totalSupply() public constant returns (uint);
22 | function totalSupplyAt(uint _blockNumber) public constant returns(uint);
23 | function balanceOf(address _owner) public constant returns (uint256 balance);
24 | function balanceOfAt(address _owner, uint _blockNumber) public constant returns (uint);
25 | function transfer(address _to, uint256 _amount) public returns (bool success);
26 | function transferFrom(address _from, address _to, uint256 _amount) public returns (bool success);
27 | function approve(address _spender, uint256 _amount) public returns (bool success);
28 | function approveAndCall(address _spender, uint256 _amount, bytes _extraData) public returns (bool success);
29 | function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
30 | function mint(address _owner, uint _amount) public returns (bool);
31 | function importPresaleBalances(address[] _addresses, uint256[] _balances, address _presaleAddress) public returns (bool);
32 | function lockPresaleBalances() public returns (bool);
33 | function finishMinting() public returns (bool);
34 | function enableTransfers(bool _value) public;
35 | function enableMasterTransfers(bool _value) public;
36 | function createCloneToken(uint _snapshotBlock, string _cloneTokenName, string _cloneTokenSymbol) public returns (address);
37 |
38 | }
--------------------------------------------------------------------------------
/contracts/SafeMath.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 |
4 | /**
5 | * @title SafeMath
6 | * @dev Math operations with safety checks that throw on error
7 | */
8 | library SafeMath {
9 | function mul(uint256 a, uint256 b) internal constant returns (uint256) {
10 | uint256 c = a * b;
11 | assert(a == 0 || c / a == b);
12 | return c;
13 | }
14 |
15 | function div(uint256 a, uint256 b) internal constant returns (uint256) {
16 | // assert(b > 0); // Solidity automatically throws when dividing by 0
17 | uint256 c = a / b;
18 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold
19 | return c;
20 | }
21 |
22 | function sub(uint256 a, uint256 b) internal constant returns (uint256) {
23 | assert(b <= a);
24 | return a - b;
25 | }
26 |
27 | function add(uint256 a, uint256 b) internal constant returns (uint256) {
28 | uint256 c = a + b;
29 | assert(c >= a);
30 | return c;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/contracts/TokenFactory.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | import './ProofToken.sol';
4 | import './Ownable.sol';
5 |
6 | contract TokenFactory {
7 |
8 | function createCloneToken(
9 | address _parentToken,
10 | uint _snapshotBlock,
11 | string _tokenName,
12 | string _tokenSymbol
13 | ) public returns (ProofToken) {
14 |
15 | ProofToken newToken = new ProofToken(
16 | this,
17 | _parentToken,
18 | _snapshotBlock,
19 | _tokenName,
20 | _tokenSymbol
21 | );
22 |
23 | newToken.transferControl(msg.sender);
24 | return newToken;
25 | }
26 | }
--------------------------------------------------------------------------------
/contracts/TokenFactoryInterface.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | import './ProofToken.sol';
4 |
5 | contract TokenFactoryInterface {
6 |
7 | function createCloneToken(
8 | address _parentToken,
9 | uint _snapshotBlock,
10 | string _tokenName,
11 | string _tokenSymbol
12 | ) public returns (ProofToken newToken);
13 | }
--------------------------------------------------------------------------------
/contracts/TokenSale.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.15;
2 |
3 | import './SafeMath.sol';
4 | import './Pausable.sol';
5 | import './ProofTokenInterface.sol';
6 | /**
7 | * @title Tokensale
8 | * Tokensale allows investors to make token purchases and assigns them tokens based
9 |
10 | * on a token per ETH rate. Funds collected are forwarded to a wallet as they arrive.
11 | */
12 | contract TokenSale is Pausable {
13 |
14 | using SafeMath for uint256;
15 |
16 | ProofTokenInterface public proofToken;
17 | uint256 public totalWeiRaised;
18 | uint256 public tokensMinted;
19 | uint256 public totalSupply;
20 | uint256 public contributors;
21 | uint256 public decimalsMultiplier;
22 | uint256 public startTime;
23 | uint256 public endTime;
24 | uint256 public remainingTokens;
25 | uint256 public allocatedTokens;
26 |
27 | bool public finalized;
28 |
29 | bool public proofTokensAllocated;
30 | address public proofMultiSig = 0x99892Ac6DA1b3851167Cb959fE945926bca89f09;
31 |
32 | uint256 public constant BASE_PRICE_IN_WEI = 88000000000000000;
33 | uint256 public constant PUBLIC_TOKENS = 1181031 * (10 ** 18);
34 | uint256 public constant TOTAL_PRESALE_TOKENS = 112386712924725508802400;
35 | uint256 public constant TOKENS_ALLOCATED_TO_PROOF = 1181031 * (10 ** 18);
36 |
37 |
38 |
39 | uint256 public tokenCap = PUBLIC_TOKENS - TOTAL_PRESALE_TOKENS;
40 | uint256 public cap = tokenCap / (10 ** 18);
41 | uint256 public weiCap = cap * BASE_PRICE_IN_WEI;
42 |
43 | uint256 public firstDiscountPrice = (BASE_PRICE_IN_WEI * 85) / 100;
44 | uint256 public secondDiscountPrice = (BASE_PRICE_IN_WEI * 90) / 100;
45 | uint256 public thirdDiscountPrice = (BASE_PRICE_IN_WEI * 95) / 100;
46 |
47 | uint256 public firstDiscountCap = (weiCap * 5) / 100;
48 | uint256 public secondDiscountCap = (weiCap * 10) / 100;
49 | uint256 public thirdDiscountCap = (weiCap * 20) / 100;
50 |
51 | bool public started = false;
52 |
53 | event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
54 | event NewClonedToken(address indexed _cloneToken);
55 | event OnTransfer(address _from, address _to, uint _amount);
56 | event OnApprove(address _owner, address _spender, uint _amount);
57 | event LogInt(string _name, uint256 _value);
58 | event Finalized();
59 |
60 | function TokenSale(address _tokenAddress, uint256 _startTime, uint256 _endTime) public {
61 | require(_tokenAddress != 0x0);
62 | require(_startTime > 0);
63 | require(_endTime > _startTime);
64 |
65 | startTime = _startTime;
66 | endTime = _endTime;
67 | proofToken = ProofTokenInterface(_tokenAddress);
68 |
69 | decimalsMultiplier = (10 ** 18);
70 | }
71 |
72 |
73 | /**
74 | * High level token purchase function
75 | */
76 | function() public payable {
77 | buyTokens(msg.sender);
78 | }
79 |
80 | /**
81 | * Low level token purchase function
82 | * @param _beneficiary will receive the tokens.
83 | */
84 | function buyTokens(address _beneficiary) public payable whenNotPaused whenNotFinalized {
85 | require(_beneficiary != 0x0);
86 | require(validPurchase());
87 |
88 | uint256 weiAmount = msg.value;
89 | uint256 priceInWei = getPriceInWei();
90 | totalWeiRaised = totalWeiRaised.add(weiAmount);
91 |
92 | uint256 tokens = weiAmount.mul(decimalsMultiplier).div(priceInWei);
93 | tokensMinted = tokensMinted.add(tokens);
94 | require(tokensMinted < tokenCap);
95 |
96 | contributors = contributors.add(1);
97 |
98 | proofToken.mint(_beneficiary, tokens);
99 | TokenPurchase(msg.sender, _beneficiary, weiAmount, tokens);
100 | forwardFunds();
101 | }
102 |
103 |
104 | /**
105 | * Get the price in wei for current premium
106 | * @return price {uint256}
107 | */
108 | function getPriceInWei() constant public returns (uint256) {
109 |
110 | uint256 price;
111 |
112 | if (totalWeiRaised < firstDiscountCap) {
113 | price = firstDiscountPrice;
114 | } else if (totalWeiRaised < secondDiscountCap) {
115 | price = secondDiscountPrice;
116 | } else if (totalWeiRaised < thirdDiscountCap) {
117 | price = thirdDiscountPrice;
118 | } else {
119 | price = BASE_PRICE_IN_WEI;
120 | }
121 |
122 | return price;
123 | }
124 |
125 | /**
126 | * Forwards funds to the tokensale wallet
127 | */
128 | function forwardFunds() internal {
129 | proofMultiSig.transfer(msg.value);
130 | }
131 |
132 |
133 | /**
134 | * Validates the purchase (period, minimum amount, within cap)
135 | * @return {bool} valid
136 | */
137 | function validPurchase() internal constant returns (bool) {
138 | uint256 current = now;
139 | bool presaleStarted = (current >= startTime || started);
140 | bool presaleNotEnded = current <= endTime;
141 | bool nonZeroPurchase = msg.value != 0;
142 | return nonZeroPurchase && presaleStarted && presaleNotEnded;
143 | }
144 |
145 | /**
146 | * Returns the total Proof token supply
147 | * @return totalSupply {uint256} Proof Token Total Supply
148 | */
149 | function totalSupply() public constant returns (uint256) {
150 | return proofToken.totalSupply();
151 | }
152 |
153 | /**
154 | * Returns token holder Proof Token balance
155 | * @param _owner {address} Token holder address
156 | * @return balance {uint256} Corresponding token holder balance
157 | */
158 | function balanceOf(address _owner) public constant returns (uint256) {
159 | return proofToken.balanceOf(_owner);
160 | }
161 |
162 | /**
163 | * Change the Proof Token controller
164 | * @param _newController {address} New Proof Token controller
165 | */
166 | function changeController(address _newController) public {
167 | require(isContract(_newController));
168 | proofToken.transferControl(_newController);
169 | }
170 |
171 |
172 | function enableTransfers() public {
173 | if (now < endTime) {
174 | require(msg.sender == owner);
175 | }
176 | proofToken.enableTransfers(true);
177 | }
178 |
179 | function lockTransfers() public onlyOwner {
180 | require(now < endTime);
181 | proofToken.enableTransfers(false);
182 | }
183 |
184 | function enableMasterTransfers() public onlyOwner {
185 | proofToken.enableMasterTransfers(true);
186 | }
187 |
188 | function lockMasterTransfers() public onlyOwner {
189 | proofToken.enableMasterTransfers(false);
190 | }
191 |
192 | function forceStart() public onlyOwner {
193 | started = true;
194 | }
195 |
196 | function allocateProofTokens() public onlyOwner whenNotFinalized {
197 | require(!proofTokensAllocated);
198 | proofToken.mint(proofMultiSig, TOKENS_ALLOCATED_TO_PROOF);
199 | proofTokensAllocated = true;
200 | }
201 |
202 | function finalize() public onlyOwner {
203 | require(paused);
204 | require(proofTokensAllocated);
205 |
206 | proofToken.finishMinting();
207 | proofToken.enableTransfers(true);
208 | Finalized();
209 |
210 | finalized = true;
211 | }
212 |
213 |
214 | function isContract(address _addr) constant internal returns(bool) {
215 | uint size;
216 | if (_addr == 0)
217 | return false;
218 | assembly {
219 | size := extcodesize(_addr)
220 | }
221 | return size>0;
222 | }
223 |
224 | modifier whenNotFinalized() {
225 | require(!finalized);
226 | _;
227 | }
228 |
229 | }
--------------------------------------------------------------------------------
/coverage.json:
--------------------------------------------------------------------------------
1 | {"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/ERC20.sol":{"l":{},"path":"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/ERC20.sol","s":{},"b":{},"f":{},"fnMap":{},"statementMap":{},"branchMap":{}},"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/Ownable.sol":{"l":{"18":2,"26":0,"27":0,"36":0,"37":0},"path":"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/Ownable.sol","s":{"1":2,"2":0,"3":0,"4":0},"b":{"1":[0,0],"2":[0,0]},"f":{"1":2,"2":0,"3":0},"fnMap":{"1":{"name":"Ownable","line":17,"loc":{"start":{"line":17,"column":2},"end":{"line":17,"column":20}}},"2":{"name":"onlyOwner","line":25,"loc":{"start":{"line":25,"column":2},"end":{"line":25,"column":22}}},"3":{"name":"transferOwnership","line":35,"loc":{"start":{"line":35,"column":2},"end":{"line":35,"column":56}}}},"statementMap":{"1":{"start":{"line":18,"column":4},"end":{"line":18,"column":21}},"2":{"start":{"line":26,"column":4},"end":{"line":26,"column":31}},"3":{"start":{"line":36,"column":4},"end":{"line":36,"column":804}},"4":{"start":{"line":37,"column":6},"end":{"line":37,"column":21}}},"branchMap":{"1":{"line":26,"type":"if","locations":[{"start":{"line":26,"column":4},"end":{"line":26,"column":4}},{"start":{"line":26,"column":4},"end":{"line":26,"column":4}}]},"2":{"line":36,"type":"if","locations":[{"start":{"line":36,"column":4},"end":{"line":36,"column":4}},{"start":{"line":36,"column":4},"end":{"line":36,"column":4}}]}}},"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/Pausable.sol":{"l":{"23":0,"24":0,"31":0,"32":0,"39":0,"40":0,"41":0,"48":0,"49":0,"50":0},"path":"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/Pausable.sol","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"b":{"1":[0,0],"2":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0,"5":0},"fnMap":{"1":{"name":"Pausable","line":17,"loc":{"start":{"line":17,"column":2},"end":{"line":17,"column":21}}},"2":{"name":"whenNotPaused","line":22,"loc":{"start":{"line":22,"column":2},"end":{"line":22,"column":26}}},"3":{"name":"whenPaused","line":30,"loc":{"start":{"line":30,"column":2},"end":{"line":30,"column":21}}},"4":{"name":"pause","line":38,"loc":{"start":{"line":38,"column":2},"end":{"line":38,"column":57}}},"5":{"name":"unpause","line":47,"loc":{"start":{"line":47,"column":2},"end":{"line":47,"column":56}}}},"statementMap":{"1":{"start":{"line":23,"column":4},"end":{"line":23,"column":19}},"2":{"start":{"line":31,"column":4},"end":{"line":31,"column":18}},"3":{"start":{"line":39,"column":4},"end":{"line":39,"column":16}},"4":{"start":{"line":40,"column":4},"end":{"line":40,"column":10}},"5":{"start":{"line":41,"column":4},"end":{"line":41,"column":15}},"6":{"start":{"line":48,"column":4},"end":{"line":48,"column":17}},"7":{"start":{"line":49,"column":4},"end":{"line":49,"column":12}},"8":{"start":{"line":50,"column":4},"end":{"line":50,"column":15}}},"branchMap":{"1":{"line":23,"type":"if","locations":[{"start":{"line":23,"column":4},"end":{"line":23,"column":4}},{"start":{"line":23,"column":4},"end":{"line":23,"column":4}}]},"2":{"line":31,"type":"if","locations":[{"start":{"line":31,"column":4},"end":{"line":31,"column":4}},{"start":{"line":31,"column":4},"end":{"line":31,"column":4}}]}}},"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/ProofPresaleToken.sol":{"l":{"33":0,"37":0,"42":0,"43":0,"45":0,"46":0,"50":0,"52":0,"53":0,"54":0,"56":0,"57":0,"61":0,"62":0,"63":0,"67":0,"72":0,"73":0,"83":0,"84":0,"85":0,"86":0,"94":0,"95":0,"96":0},"path":"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/ProofPresaleToken.sol","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0},"b":{"1":[0,0]},"f":{"1":1,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"fnMap":{"1":{"name":"ProofPresaleToken","line":30,"loc":{"start":{"line":30,"column":2},"end":{"line":30,"column":30}}},"2":{"name":null,"line":32,"loc":{"start":{"line":32,"column":2},"end":{"line":32,"column":20}}},"3":{"name":"balanceOf","line":36,"loc":{"start":{"line":36,"column":2},"end":{"line":36,"column":63}}},"4":{"name":"transfer","line":40,"loc":{"start":{"line":40,"column":2},"end":{"line":40,"column":60}}},"5":{"name":"transferFrom","line":49,"loc":{"start":{"line":49,"column":2},"end":{"line":49,"column":79}}},"6":{"name":"approve","line":60,"loc":{"start":{"line":60,"column":2},"end":{"line":60,"column":64}}},"7":{"name":"allowance","line":66,"loc":{"start":{"line":66,"column":2},"end":{"line":66,"column":81}}},"8":{"name":"canMint","line":71,"loc":{"start":{"line":71,"column":2},"end":{"line":71,"column":20}}},"9":{"name":"mint","line":82,"loc":{"start":{"line":82,"column":2},"end":{"line":82,"column":78}}},"10":{"name":"finishMinting","line":93,"loc":{"start":{"line":93,"column":2},"end":{"line":93,"column":51}}},"11":{"name":"calculateShare","line":100,"loc":{"start":{"line":100,"column":2},"end":{"line":100,"column":45}}}},"statementMap":{"1":{"start":{"line":33,"column":4},"end":{"line":33,"column":11}},"2":{"start":{"line":37,"column":4},"end":{"line":37,"column":27}},"3":{"start":{"line":42,"column":4},"end":{"line":42,"column":58}},"4":{"start":{"line":43,"column":4},"end":{"line":43,"column":44}},"5":{"start":{"line":45,"column":4},"end":{"line":45,"column":36}},"6":{"start":{"line":46,"column":4},"end":{"line":46,"column":15}},"7":{"start":{"line":50,"column":4},"end":{"line":50,"column":47}},"8":{"start":{"line":52,"column":4},"end":{"line":52,"column":44}},"9":{"start":{"line":53,"column":4},"end":{"line":53,"column":48}},"10":{"start":{"line":54,"column":4},"end":{"line":54,"column":54}},"11":{"start":{"line":56,"column":4},"end":{"line":56,"column":31}},"12":{"start":{"line":57,"column":4},"end":{"line":57,"column":15}},"13":{"start":{"line":61,"column":4},"end":{"line":61,"column":41}},"14":{"start":{"line":62,"column":4},"end":{"line":62,"column":41}},"15":{"start":{"line":63,"column":4},"end":{"line":63,"column":15}},"16":{"start":{"line":67,"column":4},"end":{"line":67,"column":36}},"17":{"start":{"line":72,"column":4},"end":{"line":72,"column":28}},"18":{"start":{"line":83,"column":4},"end":{"line":83,"column":41}},"19":{"start":{"line":84,"column":4},"end":{"line":84,"column":45}},"20":{"start":{"line":85,"column":4},"end":{"line":85,"column":21}},"21":{"start":{"line":86,"column":4},"end":{"line":86,"column":15}},"22":{"start":{"line":94,"column":4},"end":{"line":94,"column":25}},"23":{"start":{"line":95,"column":4},"end":{"line":95,"column":17}},"24":{"start":{"line":96,"column":4},"end":{"line":96,"column":15}}},"branchMap":{"1":{"line":72,"type":"if","locations":[{"start":{"line":72,"column":4},"end":{"line":72,"column":4}},{"start":{"line":72,"column":4},"end":{"line":72,"column":4}}]}}},"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/ProofToken.sol":{"l":{"35":1,"39":0,"43":0,"48":0,"49":0,"51":0,"52":0,"56":0,"58":0,"59":0,"60":0,"62":0,"63":0,"67":0,"69":0,"70":0,"74":0,"78":0,"79":0,"81":0,"82":0,"84":0,"89":0,"90":0,"100":0,"101":0,"103":0,"104":0,"112":0,"114":0,"115":0},"path":"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/ProofToken.sol","s":{"1":1,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0},"b":{"1":[0,0],"2":[0,0],"3":[0,0]},"f":{"1":1,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"fnMap":{"1":{"name":"ProofToken","line":34,"loc":{"start":{"line":34,"column":2},"end":{"line":34,"column":51}}},"2":{"name":null,"line":38,"loc":{"start":{"line":38,"column":2},"end":{"line":38,"column":20}}},"3":{"name":"balanceOf","line":42,"loc":{"start":{"line":42,"column":2},"end":{"line":42,"column":63}}},"4":{"name":"transfer","line":46,"loc":{"start":{"line":46,"column":2},"end":{"line":46,"column":60}}},"5":{"name":"transferFrom","line":55,"loc":{"start":{"line":55,"column":2},"end":{"line":55,"column":79}}},"6":{"name":"approve","line":66,"loc":{"start":{"line":66,"column":2},"end":{"line":66,"column":64}}},"7":{"name":"allowance","line":73,"loc":{"start":{"line":73,"column":2},"end":{"line":73,"column":81}}},"8":{"name":"claim","line":77,"loc":{"start":{"line":77,"column":2},"end":{"line":77,"column":33}}},"9":{"name":"canMint","line":88,"loc":{"start":{"line":88,"column":2},"end":{"line":88,"column":20}}},"10":{"name":"mint","line":99,"loc":{"start":{"line":99,"column":2},"end":{"line":99,"column":78}}},"11":{"name":"finishMinting","line":111,"loc":{"start":{"line":111,"column":2},"end":{"line":111,"column":51}}}},"statementMap":{"1":{"start":{"line":35,"column":4},"end":{"line":35,"column":57}},"2":{"start":{"line":39,"column":4},"end":{"line":39,"column":11}},"3":{"start":{"line":43,"column":4},"end":{"line":43,"column":27}},"4":{"start":{"line":48,"column":4},"end":{"line":48,"column":58}},"5":{"start":{"line":49,"column":4},"end":{"line":49,"column":44}},"6":{"start":{"line":51,"column":4},"end":{"line":51,"column":36}},"7":{"start":{"line":52,"column":4},"end":{"line":52,"column":15}},"8":{"start":{"line":56,"column":4},"end":{"line":56,"column":47}},"9":{"start":{"line":58,"column":4},"end":{"line":58,"column":44}},"10":{"start":{"line":59,"column":4},"end":{"line":59,"column":48}},"11":{"start":{"line":60,"column":4},"end":{"line":60,"column":54}},"12":{"start":{"line":62,"column":4},"end":{"line":62,"column":31}},"13":{"start":{"line":63,"column":4},"end":{"line":63,"column":15}},"14":{"start":{"line":67,"column":4},"end":{"line":67,"column":41}},"15":{"start":{"line":69,"column":4},"end":{"line":69,"column":41}},"16":{"start":{"line":70,"column":4},"end":{"line":70,"column":15}},"17":{"start":{"line":74,"column":4},"end":{"line":74,"column":36}},"18":{"start":{"line":78,"column":4},"end":{"line":78,"column":50}},"19":{"start":{"line":79,"column":4},"end":{"line":79,"column":40}},"20":{"start":{"line":81,"column":4},"end":{"line":81,"column":29}},"21":{"start":{"line":82,"column":4},"end":{"line":82,"column":60}},"22":{"start":{"line":84,"column":4},"end":{"line":84,"column":15}},"23":{"start":{"line":89,"column":4},"end":{"line":89,"column":28}},"24":{"start":{"line":100,"column":4},"end":{"line":100,"column":41}},"25":{"start":{"line":101,"column":4},"end":{"line":101,"column":45}},"26":{"start":{"line":103,"column":4},"end":{"line":103,"column":21}},"27":{"start":{"line":104,"column":4},"end":{"line":104,"column":15}},"28":{"start":{"line":112,"column":4},"end":{"line":112,"column":25}},"29":{"start":{"line":114,"column":4},"end":{"line":114,"column":17}},"30":{"start":{"line":115,"column":4},"end":{"line":115,"column":15}}},"branchMap":{"1":{"line":78,"type":"if","locations":[{"start":{"line":78,"column":4},"end":{"line":78,"column":4}},{"start":{"line":78,"column":4},"end":{"line":78,"column":4}}]},"2":{"line":79,"type":"if","locations":[{"start":{"line":79,"column":4},"end":{"line":79,"column":4}},{"start":{"line":79,"column":4},"end":{"line":79,"column":4}}]},"3":{"line":89,"type":"if","locations":[{"start":{"line":89,"column":4},"end":{"line":89,"column":4}},{"start":{"line":89,"column":4},"end":{"line":89,"column":4}}]}}},"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/SafeMath.sol":{"l":{"10":0,"11":0,"12":0,"17":0,"19":0,"23":0,"24":0,"28":0,"29":0,"30":0},"path":"/Users/davidvanisacker/Programming/Ethereum/Proofsuite/ProofTokenSale/contracts/SafeMath.sol","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"b":{"1":[0,0],"2":[0,0],"3":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0},"fnMap":{"1":{"name":"mul","line":9,"loc":{"start":{"line":9,"column":2},"end":{"line":9,"column":72}}},"2":{"name":"div","line":15,"loc":{"start":{"line":15,"column":2},"end":{"line":15,"column":72}}},"3":{"name":"sub","line":22,"loc":{"start":{"line":22,"column":2},"end":{"line":22,"column":72}}},"4":{"name":"add","line":27,"loc":{"start":{"line":27,"column":2},"end":{"line":27,"column":72}}}},"statementMap":{"1":{"start":{"line":10,"column":4},"end":{"line":10,"column":20}},"2":{"start":{"line":11,"column":4},"end":{"line":11,"column":31}},"3":{"start":{"line":12,"column":4},"end":{"line":12,"column":12}},"4":{"start":{"line":17,"column":4},"end":{"line":17,"column":20}},"5":{"start":{"line":19,"column":4},"end":{"line":19,"column":12}},"6":{"start":{"line":23,"column":4},"end":{"line":23,"column":17}},"7":{"start":{"line":24,"column":4},"end":{"line":24,"column":16}},"8":{"start":{"line":28,"column":4},"end":{"line":28,"column":20}},"9":{"start":{"line":29,"column":4},"end":{"line":29,"column":17}},"10":{"start":{"line":30,"column":4},"end":{"line":30,"column":12}}},"branchMap":{"1":{"line":11,"type":"if","locations":[{"start":{"line":11,"column":4},"end":{"line":11,"column":4}},{"start":{"line":11,"column":4},"end":{"line":11,"column":4}}]},"2":{"line":23,"type":"if","locations":[{"start":{"line":23,"column":4},"end":{"line":23,"column":4}},{"start":{"line":23,"column":4},"end":{"line":23,"column":4}}]},"3":{"line":29,"type":"if","locations":[{"start":{"line":29,"column":4},"end":{"line":29,"column":4}},{"start":{"line":29,"column":4},"end":{"line":29,"column":4}}]}}}}
--------------------------------------------------------------------------------
/jsdoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["node_modules/jsdoc-babel"],
3 | "babel": {
4 | "presets": [ "es2015" ],
5 | "plugins": [ "transform-async-to-generator" ]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | const config = require('../config.js')
2 |
3 | var Migrations = artifacts.require("./Migrations.sol");
4 |
5 | let wallet, gas, gasPrice;
6 | module.exports = function(deployer) {
7 |
8 | if (deployer.network == "ethereum") {
9 | wallet = config.addresses.ethereum.WALLET_ADDRESS
10 | gas = config.constants.MAX_GAS
11 | gasPrice = config.constants.DEFAULT_HIGH_GAS_PRICE
12 | } else if (deployer.network == "ropsten") {
13 | wallet = config.addresses.ropsten.WALLET_ADDRESS
14 | gas = config.constants.DEFAULT_GAS
15 | gasPrice = config.constants.DEFAULT_HIGH_GAS_PRICE
16 | } else if (deployer.network == "rinkeby") {
17 | wallet = config.addresses.rinkeby.WALLET_ADDRESS
18 | gas = config.constants.MAX_GAS
19 | gasPrice = config.constants.DEFAULT_GAS_PRICE
20 | } else if (deployer.network == "development") {
21 | wallet = config.addresses.development.WALLET_ADDRESS
22 | gas = config.constants.DEFAULT_GAS
23 | gasPrice = config.constants.DEFAULT_GAS_PRICE
24 | } else {
25 | throw new Error("Wallet not set")
26 | }
27 |
28 |
29 | deployer.deploy(Migrations, {gas: gas, gasPrice: gasPrice });
30 | };
31 |
--------------------------------------------------------------------------------
/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | const config = require('../config.js')
2 |
3 | const ProofToken = artifacts.require('./ProofToken.sol');
4 | const TokenSale = artifacts.require('./TokenSale.sol');
5 | const TokenFactory = artifacts.require('./TokenFactory.sol')
6 |
7 | let wallet, gas, gasPrice;
8 |
9 |
10 | module.exports = function(deployer) {
11 |
12 | if (deployer.network == "ethereum") {
13 | wallet = config.addresses.ethereum.WALLET_ADDRESS
14 | gas = config.constants.MAX_GAS
15 | gasPrice = config.constants.DEFAULT_HIGH_GAS_PRICE
16 | } else if (deployer.network == "ropsten") {
17 | wallet = config.addresses.ropsten.WALLET_ADDRESS
18 | gas = config.constants.DEFAULT_GAS
19 | gasPrice = config.constants.DEFAULT_HIGH_GAS_PRICE
20 | } else if (deployer.network == "rinkeby") {
21 | wallet = config.addresses.rinkeby.WALLET_ADDRESS
22 | gas = config.constants.MAX_GAS
23 | gasPrice = config.constants.DEFAULT_GAS_PRICE
24 | } else if (deployer.network == "development") {
25 | wallet = config.addresses.development.WALLET_ADDRESS
26 | gas = config.constants.MAX_GAS
27 | gasPrice = config.constants.DEFAULT_GAS_PRICE
28 | } else {
29 | throw new Error("Wallet not set")
30 | }
31 |
32 | deployer.deploy(
33 | TokenFactory,
34 | {gas: gas, gasPrice: gasPrice }
35 | )
36 | .then(function() {
37 | return deployer.deploy(
38 | ProofToken,
39 | TokenFactory.address,
40 | "0x0000000000000000000000000000000000000000",
41 | 0,
42 | "Proof",
43 | "PRFT",
44 | {gas: gas, gasPrice: gasPrice }
45 | )
46 | })
47 | .then(function() {
48 | return deployer.deploy(
49 | TokenSale,
50 | ProofToken.address,
51 | 1509541200, // November 1st 1PM GMT: 1509541200
52 | 1512133200, // December 1st 1PM GMT: 1512133200
53 | {gas: gas, gasPrice: gasPrice }
54 | )
55 | })
56 | }
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/other_test/crowdsale.js:
--------------------------------------------------------------------------------
1 | const BigNumber = web3.BigNumber
2 | let chai = require('chai')
3 | var chaiAsPromised = require('chai-as-promised')
4 | var chaiStats = require('chai-stats')
5 | var chaiBigNumber = require('chai-bignumber')(BigNumber)
6 | chai.use(chaiAsPromised).use(chaiBigNumber).use(chaiStats).should()
7 |
8 | import { DEFAULT_GAS,
9 | DEFAULT_GAS_PRICE,
10 | ether } from '../scripts/testConfig.js'
11 |
12 | import { getAddress,
13 | sendTransaction,
14 | expectInvalidOpcode,
15 | getBalance,
16 | advanceToBlock } from '../scripts/helpers.js'
17 |
18 | import { getTotalSupply,
19 | getTokenBalance,
20 | baseUnits,
21 | mintToken } from '../scripts/tokenHelpers.js'
22 |
23 | import { buyTokens,
24 | numberOfTokensFor,
25 | getWallet,
26 | getPriceInWei,
27 | getCap } from '../scripts/tokenSaleHelpers.js'
28 |
29 | import {
30 | pause,
31 | unpause } from '../scripts/pausableHelpers.js'
32 |
33 | import { transferOwnership } from '../scripts/ownershipHelpers.js'
34 |
35 | const assert = chai.assert
36 | const should = chai.should()
37 | const expect = chai.expect
38 |
39 | const ProofPresaleToken = artifacts.require('./ProofPresaleToken.sol')
40 | const ProofToken = artifacts.require('./ProofToken.sol')
41 | const TokenSale = artifacts.require('./TokenSale.sol')
42 |
43 | contract('Crowdsale', (accounts) => {
44 | console.log(web3.eth.getBalance(accounts[0]) / 10 ** 18)
45 | let fund = accounts[0]
46 | let tokenSale
47 | let tokenSaleAddress
48 | let proofToken
49 | let proofPresaleToken
50 | let proofPresaleTokenAddress
51 | let proofTokenAddress
52 | let sender = accounts[1]
53 | let receiver = accounts[2]
54 | let hacker1 = accounts[3]
55 | let hacker2 = accounts[4]
56 | let wallet = accounts[5]
57 |
58 | let startBlock
59 | let endBlock
60 |
61 | beforeEach(async function() {
62 | startBlock = web3.eth.blockNumber + 10
63 | endBlock = web3.eth.blockNumber + 20
64 |
65 | proofPresaleToken = await ProofPresaleToken.new()
66 | proofPresaleTokenAddress = await getAddress(proofPresaleToken)
67 |
68 | proofToken = await ProofToken.new(proofPresaleTokenAddress)
69 | proofTokenAddress = await getAddress(proofToken)
70 |
71 | tokenSale = await TokenSale.new(
72 | wallet,
73 | proofPresaleTokenAddress,
74 | proofTokenAddress,
75 | startBlock,
76 | endBlock,
77 | proofWalletAddress)
78 |
79 | tokenSaleAddress = await getAddress(tokenSale)
80 | })
81 |
82 | it('should be ended only after end', async function() {
83 | let ended = await tokenSale.hasEnded()
84 | ended.should.equal(false)
85 | await advanceToBlock()
86 | })
87 |
88 | describe('Initial State', function () {
89 | beforeEach(async function() {
90 | transferOwnership(proofToken, fund, tokenSaleAddress)
91 | })
92 |
93 | it('should initially set the wallet', async function() {
94 | let tokenSaleWallet = await tokenSale.wallet.call()
95 | tokenSaleWallet.should.be.equal(wallet)
96 | })
97 |
98 | it('should initially be linked to the Proof token', async function() {
99 | let tokenSaleToken = await tokenSale.proofToken.call()
100 | tokenSaleToken.should.be.equal(proofTokenAddress)
101 | })
102 |
103 | it('should initially be linked to the Proof Presale token', async function() {
104 | let tokenSalePresaleToken = await tokenSale.proofPresaleToken.call()
105 | tokenSalePresaleToken.should.be.equal(proofPresaleTokenAddress)
106 | })
107 |
108 | it('Price should be equal to 0.088 ether', async function() {
109 | let priceInWei = await tokenSale.priceInWei.call()
110 | priceInWei.should.be.bignumber.equal(0.088 * 10 ** 18)
111 | })
112 | })
113 |
114 | describe('Ownership', function () {
115 | it('should initially belong to contract caller', async function() {
116 | let owner = await tokenSale.owner.call()
117 | assert.equal(owner, fund)
118 | })
119 |
120 | it('should be transferable to another account', async function() {
121 | let owner = await tokenSale.owner.call()
122 | await transferOwnership(tokenSale, owner, receiver)
123 | let newOwner = await tokenSale.owner.call()
124 | assert.equal(newOwner, receiver)
125 | })
126 |
127 | it('should not be transferable by non-owner', async function() {
128 | let owner = await tokenSale.owner.call()
129 | await expectInvalidOpcode(transferOwnership(tokenSale, hacker1, hacker2))
130 | const newOwner = await tokenSale.owner.call()
131 | assert.equal(owner, newOwner)
132 | })
133 | })
134 |
135 | describe('End and Beginning of Presale', async function() {
136 | beforeEach(async function() {
137 | await transferOwnership(proofToken, fund, tokenSaleAddress)
138 | })
139 |
140 | it('should reject payments before start', async function() {
141 | await expectInvalidOpcode(tokenSale.buyTokens(sender, { value: 1 * ether, from: sender }))
142 | await expectInvalidOpcode(tokenSale.send(1 * ether, { from: sender }))
143 | })
144 |
145 | it('should accepts payments after start', async function() {
146 | await advanceToBlock(startBlock)
147 | await tokenSale.send(1 * ether, { from: sender }).should.be.fulfilled
148 | await tokenSale.buyTokens(sender, { value: 1 * ether, from: sender }).should.be.fulfilled
149 | })
150 |
151 | it('should reject payments after end', async function() {
152 | await advanceToBlock(endBlock)
153 | await expectInvalidOpcode(tokenSale.send(1 * ether, { from: sender }))
154 | await expectInvalidOpcode(tokenSale.buyTokens(sender, { value: 1 * ether, from: sender }))
155 | })
156 | })
157 |
158 | describe('Crowdsale', async function() {
159 | beforeEach(async function() {
160 | await transferOwnership(proofToken, fund, tokenSaleAddress)
161 | await advanceToBlock(startBlock)
162 | })
163 |
164 | it('should accepts ether transactions sent to contract', async function() {
165 | let order = { from: sender,
166 | to: tokenSaleAddress,
167 | value: 1 * ether,
168 | gas: DEFAULT_GAS,
169 | gasPrice: DEFAULT_GAS_PRICE
170 | }
171 |
172 | await sendTransaction(order).should.be.fulfilled
173 | })
174 |
175 | it('should accept ether through buyTokens function', async function() {
176 | let order = {
177 | from: sender,
178 | value: 1 * ether,
179 | gas: DEFAULT_GAS,
180 | gasPrice: DEFAULT_GAS_PRICE
181 | }
182 |
183 | await tokenSale.buyTokens(sender, order).should.be.fulfilled
184 | })
185 |
186 | it('should increase total token supply', async function() {
187 | let initialTotalSupply = await getTotalSupply(proofToken)
188 |
189 | await buyTokens(tokenSale, sender, 1 * ether)
190 |
191 | let expectedSupplyIncrease = await numberOfTokensFor(tokenSale, 1 * ether)
192 | expectedSupplyIncrease = await baseUnits(proofToken, expectedSupplyIncrease)
193 |
194 | let totalSupply = await getTotalSupply(proofToken)
195 |
196 | let supplyIncrease = (totalSupply - initialTotalSupply)
197 | supplyIncrease = await baseUnits(proofToken, supplyIncrease)
198 |
199 | expect(supplyIncrease).to.almost.equal(expectedSupplyIncrease)
200 | })
201 |
202 | it('should increase total supply by 11.36 for 10 ether raised', async function() {
203 | let initialTotalSupply = await getTotalSupply(proofToken)
204 |
205 | await buyTokens(tokenSale, sender, 1 * ether)
206 |
207 | let totalSupply = await getTotalSupply(proofToken)
208 | let supplyIncrease = (totalSupply - initialTotalSupply)
209 | supplyIncrease = await baseUnits(proofToken, supplyIncrease)
210 |
211 | expect(supplyIncrease).almost.equal(11.363636363636)
212 | })
213 |
214 | it('should transfer money to the wallet after receiving investment', async function() {
215 | let wallet = await getWallet(tokenSale)
216 | let initialWalletBalance = getBalance(wallet)
217 | await buyTokens(tokenSale, sender, 1 * ether)
218 |
219 | let walletBalance = getBalance(wallet)
220 | let balanceIncrease = (walletBalance - initialWalletBalance) / (1 * ether)
221 | expect(balanceIncrease).almost.equal(1, 3)
222 | })
223 |
224 | it('should create tokens for the sender', async function() {
225 | let initialTokenBalance = await getTokenBalance(proofToken, sender)
226 |
227 | await buyTokens(tokenSale, sender, 1 * ether)
228 |
229 | let tokenBalance = await getTokenBalance(proofToken, sender)
230 | let balanceIncrease = await baseUnits(proofToken, tokenBalance - initialTokenBalance)
231 |
232 | let expectedBalanceIncrease = await numberOfTokensFor(tokenSale, 1 * ether)
233 | expectedBalanceIncrease = await baseUnits(proofToken, expectedBalanceIncrease)
234 |
235 | expect(balanceIncrease).to.almost.equal(expectedBalanceIncrease)
236 | })
237 |
238 | it('should increase buyer balance by X for 10 ether invested', async function() {
239 | let initialTokenBalance = await getTokenBalance(proofToken, sender)
240 |
241 | await buyTokens(tokenSale, sender, 1 * ether)
242 |
243 | let tokenBalance = await getTokenBalance(proofToken, sender)
244 | let balanceIncrease = (tokenBalance - initialTokenBalance)
245 | balanceIncrease = await baseUnits(proofToken, balanceIncrease)
246 | expect(balanceIncrease).almost.equal(11.363636363636)
247 | })
248 | })
249 |
250 | describe('Buying Tokens', async function() {
251 | beforeEach(async function() {
252 | await transferOwnership(proofToken, fund, tokenSaleAddress)
253 | await advanceToBlock(startBlock)
254 | })
255 |
256 | it('should not be allowed if the contract is paused', async function() {
257 | await pause(tokenSale, fund)
258 | let initialBalance = await getTokenBalance(proofToken, sender)
259 |
260 | let params = { from: sender, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
261 | await expectInvalidOpcode(tokenSale.buyTokens(1, params))
262 |
263 | let balance = await getTokenBalance(proofToken, sender)
264 | balance.should.be.equal(initialBalance)
265 | })
266 |
267 | it('should be allowed if the contract is paused and unpaused', async function() {
268 | let initialBalance = await getTokenBalance(proofToken, sender)
269 |
270 | await buyTokens(tokenSale, sender, 1 * ether)
271 | await pause(tokenSale, fund)
272 | await unpause(tokenSale, fund)
273 | await buyTokens(tokenSale, sender, 1 * ether)
274 |
275 | let balance = await getTokenBalance(proofToken, sender)
276 | let balanceIncrease = await baseUnits(proofToken, balance - initialBalance)
277 | expect(balanceIncrease).to.almost.equal(22.7272727272)
278 | })
279 |
280 | it('should not throw if purchase hits just below the cap', async function() {
281 | let cap = await getCap(tokenSale)
282 | let priceInWei = await getPriceInWei(tokenSale)
283 | let initialBalance = await getTokenBalance(proofToken, sender)
284 |
285 | let amount = cap * priceInWei - 1
286 | let expectedTokens = await numberOfTokensFor(tokenSale, amount)
287 |
288 | await buyTokens(tokenSale, sender, amount)
289 |
290 | let balance = await getTokenBalance(proofToken, sender)
291 | let balanceIncrease = balance - initialBalance
292 |
293 | expect(balanceIncrease).almost.equal(expectedTokens, 3)
294 | })
295 |
296 | it('should throw if the number of tokens exceeds the cap', async function() {
297 | let cap = await getCap(tokenSale)
298 | let priceInWei = await getPriceInWei(tokenSale)
299 | let initialBalance = await getTokenBalance(proofToken, sender)
300 |
301 | let amount = cap * priceInWei * (1.001)
302 | let params = { value: amount, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
303 | await expectInvalidOpcode(tokenSale.buyTokens(sender, params))
304 |
305 | let balance = await getTokenBalance(proofToken, sender)
306 | balance.should.be.equal(initialBalance)
307 | })
308 | })
309 | })
310 |
311 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "truffle-init-webpack",
3 | "version": "0.0.2",
4 | "description": "Frontend example using truffle v3",
5 | "scripts": {
6 | "lint": "eslint ./",
7 | "build": "webpack",
8 | "dev": "webpack-dev-server",
9 | "coverage": "./node_modules/.bin/solidity-coverage",
10 | "test": "truffle test",
11 | "watch-test": "watch-run -p 'contracts/*.sol, test/*.js, scripts/*.js' truffle test"
12 | },
13 | "author": "Douglas von Kohorn",
14 | "license": "MIT",
15 | "devDependencies": {
16 | "babel-cli": "^6.22.2",
17 | "babel-core": "^6.22.1",
18 | "babel-eslint": "^6.1.2",
19 | "babel-loader": "^6.2.10",
20 | "babel-plugin-transform-async-to-generator": "~6.24.1",
21 | "babel-plugin-transform-runtime": "^6.22.0",
22 | "babel-preset-env": "^1.1.8",
23 | "babel-preset-es2015": "~6.24.1",
24 | "babel-register": "^6.22.0",
25 | "copy-webpack-plugin": "^4.0.1",
26 | "coveralls": "~2.13.1",
27 | "css-loader": "^0.26.1",
28 | "eslint": "^3.14.0",
29 | "eslint-config-standard": "^6.0.0",
30 | "eslint-plugin-babel": "^4.0.0",
31 | "eslint-plugin-mocha": "^4.8.0",
32 | "eslint-plugin-promise": "^3.0.0",
33 | "eslint-plugin-standard": "^2.0.0",
34 | "html-webpack-plugin": "^2.28.0",
35 | "istanbul": "~0.4.5",
36 | "jsdoc-babel": "~0.3.0",
37 | "json-loader": "^0.5.4",
38 | "solidity-coverage": "~0.2.2",
39 | "style-loader": "^0.13.1",
40 | "truffle-contract": "^1.1.11",
41 | "web3": "^0.18.2",
42 | "webpack": "^2.2.1",
43 | "webpack-dev-server": "^2.3.0"
44 | },
45 | "dependencies": {
46 | "@digix/tempo": "~0.2.0",
47 | "@digix/truffle-lightwallet-provider": "~0.1.2",
48 | "async-request": "~1.2.0",
49 | "await-each": "~1.1.0",
50 | "bluebird": "~3.5.0",
51 | "chai": "~4.1.2",
52 | "chai-as-promised": "~7.1.1",
53 | "chai-bignumber": "~2.0.1",
54 | "chai-stats": "~0.3.0",
55 | "csv-parser": "~1.11.0",
56 | "csvdata": "~1.4.0",
57 | "ethereum-address": "0.0.4",
58 | "ethereumjs-testrpc": "~4.1.3",
59 | "json2csv": "~3.11.1",
60 | "moment": "~2.19.1",
61 | "solc": "~0.4.17"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/scripts/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.1.0",
3 | "command": "Chrome",
4 | "osx": {
5 | "command": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
6 | },
7 | "args": [
8 | "${file}"
9 | ]
10 | }
--------------------------------------------------------------------------------
/scripts/addresses.csv:
--------------------------------------------------------------------------------
1 | Addresses,
2 | 0xcaf15d9cd7cfd573964e3dc88fc6ffea25f89d8f,
3 | 0xf190f0193b694d9d2bb865a66f0c17cbd8280c71,
4 | 0xecd7da67e6563bbddfc2ddff9ba2632c721af181,
5 | 0x31d04a32f22022ec66afe6c2351db768ed32b873,
6 | 0xc7c78f87e2e8d1d55104c8f6fae07966cfc577fd,
7 | 0x72aed3d59cc889b8ab5d943c703f45c4aeaebf86,
8 | 0x6847dedbb505b0b075b98db8f34f1d62f85e0d9d,
9 | 0xac1d10865db58adba0826d94734129ec8a5741d7,
10 | 0xfe8ef260e63a3388bb3f3174cf080f4423414100,
11 | 0x622b2c840d856181661482a2f7d9a5a41e0f992a,
12 | 0xdfa352daf510611ecc1a4ea0d02d6cae8cc3e2e0,
13 | 0x2746dc307f68a8346e9ab34aec63ab358e6dab82,
14 | 0x9c6d12aaa2fb615467c36b4db6b7e3402fb4f45f,
15 | 0x904367561bae5b96b4332c4c5ec338be097b3240,
16 | 0x16ae23df74c294c4fa4c81b278e7c94c25df8c75,
17 | 0x39fc4cdaa0e79efe7687822f1c0bacc87e1deede,
18 | 0x65c6f8dce120363cad39c85e4e5d643cf8126a83,
19 | 0x019dd0bbd3693f838a544df08ed4e2348d82d7a7,
20 | 0x20621e35f40cb15fe63d1af047413a6c5dc304b8,
21 | 0x80f564f022d22730ef980753f97be31b9fe28aae,
22 | 0xc22d2aeecc87e3907c277457e0152deb01c4a55a,
23 | 0x8761e0dd63d14cf566acf4b730f3540f164b6b56,
24 | 0xf7bad6c588967b9a512a423b21a3856744f8d6d8,
25 | 0xe5d93dd474988b60b354339da3a845d9cd35ec5f,
26 | 0x907f20132c1b706026987d592aa6f5bfe83ff314,
27 | 0xb0febed47971f087695d66ea548599f722cd67a5,
28 | 0x763d5862600d0326e14541c0687e79888999b9ab,
29 | 0x5721e592da25b96edd4d44c632cb841ac7ac47bb,
30 | 0x8cbc229cad155b95b4174647ba705d6a414b8cca,
31 | 0x77f6d9261dd8e45c0e8555aa86ab1648da9b95c3,
32 | 0x8c13278a1d8310cd4c6943eb17fad81765992431,
33 | 0xf062ceb02b73515c603707458cb3ffdf484eeb5a,
34 | 0xe0dd6cd8f2053e34ee34bb4c96c16d7e487896db,
35 | 0x62356e055f2165d0c5e812a7445700727a7934da,
36 | 0x9926df844af52a567929c2b32133ccf1c66dd4fd,
37 | 0x0e3374a49caa66c34eda91517dd5de77a9a4bbee,
38 | 0x49fc5195aad930b4df3ec1e50bb14af3586f0793,
39 | 0x553315181e9d643831936b90d63221a335c793ef,
40 | 0xa5959231dda9b429668bf198aa3580d05eb12f2e,
41 | 0xcd5164c8c8a6c4d0c49e6fa5872435c33ab42af5,
42 | 0x37aa7b1343faa68806f453f45b09dd24a1c8f3d4,
43 | 0x3b412c92e78fe2a323a5fc7cd9d31fa0226ffe14,
44 | 0xe92356c05d03fce81063caaafca1493ef6619445,
45 | 0xdd41883adc2e8db3d3e52ae06ce754ab7563a53b,
46 | 0x349b49ac381d097b12f38747447776a0b4d91bfc,
47 | 0x2198eefc694f5d50634a950e10074a11442f41a8,
48 | 0x42d2184dac8580e6224b361a36ca3a917f7ea67b,
49 | 0x01405ab95de872f1745d6b88a155f00f91a7e93e,
50 | 0x7a03a44fe2c6f98debc35800a6899ccf0869be71,
51 | 0x38ea9aeb4a849f9accde0c17ccfaeeb53ba6a393,
52 | 0x009b740f1670af3a6b62d661f182f15a24a010ae,
53 | 0xd6dda35c4216e343b325ccffe0615accae1f82b0,
54 | 0xea9900f8b55efc75c9bca99377e0f026e537544b,
55 | 0x38148ecc2078da7f65e6233dda28efaf4c51e96f,
56 | 0x100dbb75eab5d98ad65ef16483aaa68e68aafbc5,
57 | 0x9e108a4aaa86d2edc1fe4e393c8dfb0f37433559,
58 | 0x67d33cf1c7c699078f86d517a5a1cd1444a1e85c,
59 | 0x712033cf8adc1e60beadb8b52c8a02f02bffe336,
60 | 0xee9baf220c6afe2e846d1788e53ca5a0d3dcb339,
61 | 0xd082c621b2a166b90ab607b11decc4e038045177,
62 | 0x0a8966d44be0272295814e876791431791440256,
63 | 0x9f9f6768fcd665b0ae17f02601a24a60d1eb5dab,
64 | 0x5fe218e03a4a0ccd7f3eeac9a51fd23c0fc369a1,
65 | 0x4bd120e887cc82285aff8408dc208ed32b132bb3,
66 | 0x8d21e3c8993633546e89cb4a24e5c0a5bc4d97e5,
67 | 0x54ce1d1fc211817f280c5e123eb131d7a0b0beb5,
68 | 0xda4cc246162e13f26864cacf19152695d252e671,
69 | 0xac463695dcdf0aa5c16fd74d6be2b831b0512971,
70 | 0x874f59a177348ae3d540d58ac8c5d23a4e77b1e3,
71 | 0x9c79aef1d586452220ff23fa6b7791fcae1e7edb,
72 | 0x6229cf71deccb5d87767e747f5a5c7738db7e40f,
73 | 0x1bf32181e831dbc781eeb850d58f801495c4c93d,
74 | 0xf085548d7bbf66b8731e1a16bd891cad98cb102a,
75 | 0x8c4531b3f4cdfee616a44eaef29b5b5ee60cdf6d,
76 | 0x486291fea9e334ea87efbac640d7d50ffc7bf8c3,
77 | 0xb9c5b4bf86119fb67cc6f3df9632de2b46648143,
78 | 0x901b68e2099f83dcd6e443c86146969ef837ed37,
79 | 0x4866e8a3683d5b7fca9dabfb9d1188a4a152e976,
80 | 0x66ff831f74b212bc5b787c4401a5bc63812aa592,
81 | 0x4089bc81b3e2e986fbd429e03094faf6685200db,
82 | 0x351faf0b10e7d80fbaa8726b41825a71b9922c95,
83 | 0x23cbe4413e92c10c2edf9e7fab336d35be555d86,
84 | 0x0a70de1a644ced8488ec91b4b463826cbf4b5000,
85 | 0xb18b8edb5d4d1fdff2488714747b609941433ea0,
86 | 0xd8c184f93f11c591da6e321c8288c6dba85da99e,
87 | 0x6ba366de900785e24c605e4a8b5261bb23a97fe0,
88 | 0x97dfdcd746dd32b87aaa2d1a0b292f1a38c77aab,
89 | 0x7089a6315f2642ea1f21f81d5fde64f20f80f75e,
90 | 0x8a11d3d03629fbd5cae5f8ef0743bae86868d040,
91 | 0x240d90a0e69ad8f5de91ddcf5fc83cdc30631f04,
92 | 0x6653acb6d74ac95f750a687177c5c3d6a5f14c4d,
93 | 0x081af29ee22c5b902bc6e9c3ce7fa9de77ce8266,
94 | 0xf81753501afc55776320d567c3af6fcdad1204cf,
95 | 0x945ef6fb870fce7614626070af43a95d482fd99a,
96 | 0x7862e990963405616afd1e08cd369433a87adb3a,
97 | 0x8c245d87069a4e463b954778dad9df0039876a9e,
98 | 0x2b8f14e64b3be49c75c816a6e7d9596b259656ad,
99 | 0x0870f0b06a5009d9f6bdad4d3961b4639bb96750,
100 | 0x123e084fc361a878aef966df784f6b3774084028,
101 | 0x971d97f261abb1ecb9967878f45d7be1b374c81d,
102 | 0xedbaaf0005e47f8cd1e70472e93d33543ce1d38e,
103 | 0x3032967bb88c1289c49d9c8a696e8303ee9b7d88,
104 | 0x3ab79bb7d1e17730ab32a28019d890c02c6197f4,
105 | 0x95a4ac9070051437263a019028e0fb7f0c9d12a0,
106 | 0x8fbaf4d323ba4031f8c1c8614317aefb65c626dc,
107 | 0xc60debaa978d0c215c37859f8b59b07910afe807,
108 | 0x76927e2ccab0084bd19cee74f78b63134b9d181e,
109 | 0x927c78cb90407aa4b4e8e12497022e689cc5cb11,
110 | 0xd80b5f92b713a3ee048a752faf889734a4a1db93,
111 | 0xefca48c0672c6ddd1aedc84d7f54ec1b130cf854,
112 | 0xb23b9c52fc16beb6d44e243ba73936a65fc9b709,
113 | 0x7202cba14b504ac90f49aea2b698530fde9481dd,
114 | 0x782b899b1468051b01581548011660b9b1974cab,
115 | 0x8324de24e3c064af46e0dfaf146d392084e38f0c,
116 | 0x4cd24ceb901f903958f2d205d2fc218efa9f3d72,
117 | 0x79785c9729dc6135ff3060d1d8b08780ceb51668,
118 | 0x17bb4076ab59e0ef20ad5a873ab4b5341bf01b78,
119 | 0xb1b33acc4e491ad70f5837250defa92c3816f539,
120 | 0x6dd3a7060d58c8400e13dee3a63fafc8b1f7a7d5,
121 | 0x4e061bae4a29035c55f62a93b339bc57a9073aaf,
122 | 0x10af69bd4435e2c09eaa447eb89a5d3d407f5f47,
123 | 0x6a49dd97e18106c163a9fc6bca3afeb200656f49,
124 | 0xb5d365aca3e16068ab0eb3b39acf6db62c789267,
125 | 0x38a92bb6290284033b5871477fcdc2dc9a744baa,
126 | 0xf6d61560d1b6e70ab61cc58b0daa5b1dff742351,
127 | 0x18addb4b0ea01ad018417d7de4e37b9b6d35c734,
128 | 0xa3b1af9c33c6fdf7852db56263a44b93fb6f687b,
129 | 0xc2116c5a7533d8619c574ce70312f7c2306c00fd,
130 | 0x8f4e9d43583b7d4b8cff5a027220e36401c12b8e,
131 | 0x29809ede7cbe49c6fe1c1dd40513a7bda438473a,
132 | 0x4931b973792aa349108884a26ad0502690f10cdc,
133 | 0x620703fcd6a3ef6773511ef0bc45a558e5647a8c,
134 | 0x2db04d075c2a96e65d8beef44879ed8d07167384,
135 | 0xcaee01dd455e90ac98d84ae847d22261315db192,
136 | 0xdcbbbd8e22d9945f062909923d4524b9630a32ca,
137 | 0xdde972259b65433c769774e504b312de359c031a,
138 | 0x8d3748096d58695246d8735bba837098b8d3fdd7,
139 | 0x932c23938b9bbfaad91ddaf938c622d315eeef34,
140 | 0x739066ed2d1718fd100cec4d9f347382ec6440dc,
141 | 0xb3fa0fa3682bbafaeb95ef288e841609baa5c68b,
142 | 0x59e5fe8a9637702c6d597c5f1c4ebe3fba747371,
143 | 0x66eb0de38cdbbd157d6940b9542a6ca3c98e9080,
144 | 0xc9d4c2fc8c1401eeaa18c048704934f616ed8002,
145 | 0xca14e2076784f7486cf9c1cb4afe194af96bf3fe,
146 | 0x86834a65e12fc6fa4b564b8d0f6b98a4caf88f50,
147 | 0xe2190203932edc3cf358cb497d165a57a0711f77,
148 | 0xf428237037e5c0acf0751f9b42b83d7b4903d305,
149 | 0x89a94b48b21d3b5f959305643d3c71dc88cc7fbc,
150 | 0xe207214e3bc14154f22a59144ccdff6099ca6567,
151 | 0x1eccd61c9fa53a8d2e823a26cd72a7efd7d0e92e,
152 | 0x3833f8dbdbd6bdcb6a883ff209b869148965b364,
153 | 0x9b422e571eb2cb9837efdc4f9087194d65fb070a,
154 | 0x120c322c0b1477a5c2eeb6f9f06d2c98797f485f,
155 | 0xbe6b82da1815de15c1798f2ea58031d793275ff1,
156 | 0x0c38aa3d82aa58ddd9ff8a0ced05f8995950ae4d,
157 | 0x00e96c34d0d80fc23d730ac0702c86ac746f5534,
158 | 0x34b2cf5894ee3e0537e8f45cae265e68d4df4d8c,
159 | 0x69e753860e3a6bb1fead78ab5b5e573e909108c8,
160 | 0xaad68b51814179146d56e824e9bba8f2b5be4f1e,
161 | 0x22c6a17c9d68d0d8cb057435ab087943a62acbbd,
162 | 0x8c3fdeed9f2f79d294300b4b4d182a814107cf6d,
163 | 0x196d791102f53abad22b8d26f5896c4a48146432,
164 | 0x670be3b80f91b0749146a527e7ffbe1397405e9b,
165 | 0x33d87b186a47beb965fdfa207da1ae00d2d7b812,
166 | 0xa106379acb22df279f1ac3c0299742531b3ba6ee,
167 | 0xb2dd65f58594ce19fcfa7daac204587a3287899b,
168 | 0x525a7eb5dbd784feee9a4667f560406f1ea5367a,
169 | 0x26eeb2711ac35bf1c88b6c0bff75a4dd9e02d636,
170 | 0x6ed8cd17ee5453e17eb731a6b2004af53ea1f26a,
171 | 0xf8bad169cb40a0471d2f30b5772bf2ab7b7c0ee8,
172 | 0xbd131d488746eb914fbb4174b783a1b3d77f25e2,
173 | 0x2764281f229fd932b93c5bc9bf3ed2f7ebdd8d9c,
174 | 0x2707bcc067112cd420159b667c47f1dbfc858df2,
175 | 0xb93147f598f8fc20f9cd6276e56b49dfb608eb16,
176 | 0x22b0ac0be4633f57fa4457268ad365c11227e172,
177 | 0xa87d8906eabb8dfb38cc2370a36afaf013d51857,
178 | 0xb904c6901359606d7954bc0dcaaabad3ac33d6c4,
179 | 0x96921dd0a92ed047954d977e4363ec15a0b807d8,
180 | 0x1f4b0a926e0a1b492bb17bfdb8647d658701b08c,
181 | 0x597aa8e340582363f74acc894b51447a2b7d040c,
182 | 0x2f16cc0f50b1e7088177f71ab02985d4daaf7a03,
183 | 0xd4f756dadd2eb06bd14066a882f611636bf16129,
184 | 0xf59fd77afe562aa4e5b66da6e7a67b4651fac538,
185 | 0x1f81da5cc554766d3626dae05bdc6515522bb00f,
186 | 0x8f53518d306cd730652b166005aaaa1f1dd0c137,
187 | 0x18cb0c10e271fa2daca76fb03afe0fc02e83ab74,
188 | 0x9ea60ba8a75f47757f516fb1b8d48d848504a26c,
189 | 0x5ad003a9a02037b196362784f4a53e72198a0a47,
190 | 0xec9e1351c0dcc363b4d027f93ef196b023f0794f,
191 | 0x95dc704ddaa7708f7c8ec220c3f19fdfd81ae708,
192 | 0xf60bddbf39c3e60a50b328230b851a211db134c7,
193 | 0xa55638362ceda5245fa87471ac80189e8d7ad5c4,
194 | 0x82d99d98115565d2a58e99fc53704cee56e3c0de,
195 | 0x71a93ff96b59b96d2caf474b9a79a51f5b043dc3,
196 | 0x43ffdc79fbcedf718a19ad7d7eb2a705696546e4,
197 | 0xfd5a044f5211b1054d6e18b9cb6ece538ec3057f,
198 | 0x8a9354835138d2367923622f27d6c377546175e0,
199 | 0x609723885766759aaf726c241afaa3fb82a3580a,
200 | 0xcc979952371ba7873983b3fadd38649496d206af,
201 | 0xd4bccbde6dc6c922edd96fa1bfa82f03454fbfd8,
202 | 0x7fd44298916ebcb7ffd80bc2b44c918e5333ec3d,
203 | 0xf2787ca2de0b2d20c6cc9bc1ef3519d7eeba47ae,
204 | 0xc285d754df88d0283adbee7027bdb38f3a38adb6,
205 | 0x81c831e3ed24d4b97585c1a371c7aabeba839bb4,
206 | 0xdba4fd71bcd12a9188a365fccc796c65381b49f1,
207 | 0x071b572c7d6b423973078ae08981d944961775f4,
208 | 0x056d01e62c5b2568517d3af63447076e1456998c,
209 | 0x1b3f224bf8fdb4c23fbd6056fe062ffd456b09d6,
210 | 0x91d7833bf076eb16d51f5bff598ad42f4e79bb51,
211 | 0x92a898d46f19719c38126a8a3c27867ae2cee596,
212 | 0xc24b1a1a4cde1c628202a345708653334d30f05f,
213 | 0x31e156678b8f96005f14f91676bef642c28ad06c,
214 | 0x8d12a197cb00d4747a1fe03395095ce2a5cc6819,
215 | 0x74f9d4f1f58686fb8725c29f9ab2cdd2913dd1f0,
216 | 0x2c21e83a76b2dea9fb85885257eb1ac3f82da450,
217 | 0x34bd23da4689788dfa8e6521f979f5eaa3831b3e,
218 | 0xef3c3dfb36ae7c32f509ec1676659ff86ab3f394,
219 | 0x666d77e5b67ddb1f861b3485b70c60b5256a3aa8,
220 | 0xe9ebee76a902b6536c0bddf79ac4c4343e5bdbfb,
221 | 0x8038339ca5c71a11eb321986bf7acd1282da84d5,
222 | 0xad032694466f2b56b11e8258747af91bf72ed791,
223 | 0xf697eeca8130513cc59b1a3ebcc098ba5c10d80c,
224 | 0x4ea5fb82a9ad7cae9bc4357ee0368eb73f9de17d,
225 | 0x00c5a971dafa5e8e2dcff0af9571e2dbe4f4a0bf,
226 | 0x2f2862e9818ca4ada4ae69e700e3a806236d997e,
227 | 0xc7075ed6bf05549ed8e0d6b11f58721040ab4d05,
228 | 0xc9dd260b16b9402e6244f34a8c52dfdcd6eb9113,
229 | 0xce6d2f7b55eb3066c14b4047b2017d7000697e14,
230 | 0x73aa55afb6f0258b2e8b723b7598eb3b3a8312ed,
231 | 0x76bf705e423ccc18f699f275c7bc2d506090acda,
232 | 0x68f521a871ddd406a57121bf7246c7574bc3cb62,
233 | 0x41bacae05437a3fe126933e57002ae3f129aa079,
234 | 0xcc8f79950bfe3d292608321351c4d45d497a7c6d,
235 | 0x63eed78361018f43cb46fa48a6122e004d963a2d,
236 | 0x3a02b24bf0bfc7b9c485eba503fd73e751ca0b00,
237 | 0x4062b2b12b354bf8f9398685a29e1f5e534f95a8,
238 | 0x286f0171bb5c940314c83c9cd9e355106a7de7e7,
239 | 0x33a96b5993f65e26ad4f51b3d3ccea513271b923,
240 | 0xce838139e92080e8e1266092bafb64d1e43dd139,
241 | 0x133f9d96901e3727596660d32dbdcbcf57c03dbb,
242 | 0xfa60838ac163b8b44108b92c8b64c7c15fd5d1bd,
243 | 0x4fc15720ac8dfbdd20aa47c518cf26ee2fc39ef7,
244 | 0x4e89c8b0cefe3b3239a168325baacec8c1cee218,
245 | 0x450f5f260559e4861cd703b61bb9e5e0c622ef29,
246 | 0x4ecec940deabb584b43f21c91b1238bd43b5e7eb,
247 | 0x9e3e93fc983d84e6397e35bc5cd3c33783041f35,
248 | 0xb8c5bb7d01294f5148488786ac9578e97ffb95fd,
249 | 0xcab61b858a344ad4c878c60de62b2019d3e00aed,
250 | 0x7a82fb208303aab2369105ba03c9c0146ac8fd86,
251 | 0x607e4d73800332bf29ff7729a8b519cce7d54202,
252 | 0xcb37a8f731b4db7238d4f4683824ca54decdbce2,
253 | 0x4a789c070535b51ef86628dc995813c6c2eddb32,
254 | 0x70540666f778b7111d62cd6a9ea8a35f44d4076a,
255 | 0xdee028822bc40ac1d6bb042c2378796efdce8bd9,
256 | 0xab697f58c8e9525df5337052cd71d1ba6fff7306,
257 | 0x56532086984e9f6e806cd20c0d241f97b8fe18d9,
258 | 0x4c5aa30f63955ed90e2c47b401dd67e7a409735b,
259 | 0x2beea5ee986b5fd028f4fa64f832020f3ca35aad,
260 | 0x58562bcb3ccaa3b773053eb61d700c7a20884b50,
261 | 0x801f28a3c0813395ed6f2a7216fa16c88917a542,
262 | 0x3e2021221b0bb5e2d1ceda9f024ed9804b055708,
263 | 0x4212fb436bb377cc3c10f5e2f16894daefa68f2f,
264 | 0xa72c38bd35ef32267b6a9315ad3cf36e2624767e,
265 | 0x53dd1454af6da0c6c80230c6f4ba06352b46fd7c,
266 | 0x6aaf4ca8f73f28acf8ae1d8d90465cc9026fd415,
267 | 0xebb62cf8e22c884b1b28c6fa88fbbc17938aa787,
268 | 0x7bacdb8b1aa9390a1ceee85c1e26a9f03671fd43,
269 | 0x0644c1a6d61e0994c73c86febdf64ec8432b1013,
270 | 0x0bbde14072a835903f2f687dd64dd990680e967f,
271 | 0xd07d158d62b1f2c657ceb7331b75de868b83dccf,
272 | 0x60fee5affc433a53e8751fe55fc4bd1794f5ff51,
273 | 0x13148f7a44f78415ba50e8d6a9d7f97ad5a5aff6,
274 | 0x2b5dbb6907816e4ab6182bf58dae543b48ff319a,
275 | 0x7d2330b2906bfdf1c192fc8b750081a2ee6f8328,
276 | 0x57d0c97313bef304f99f338285de6fdce26d0486,
277 | 0xd82ab13c28b70d2a904e03faf15c48df1c970926,
278 | 0x26444302825fbe13d5a5d1c7e7c5759ca67f490d,
279 | 0x32035a7f88db2ae8b66e84fc9333084fa27d88fb,
280 | 0x388e431d70958a5f338a94081d244ec82165ba9b,
281 | 0x7401d01a9bcf8ee5d44b57f255d8a7c14a12d80c,
282 | 0x0fac3479b2eacb02445932e5b65122d6ffab3db8,
283 |
--------------------------------------------------------------------------------
/scripts/controlHelpers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Ownership helpers module
3 | * @module ownership-helpers
4 | */
5 |
6 | var Promise = require('bluebird')
7 | import { gas } from './testConfig.js'
8 | import { waitUntilTransactionsMined } from './helpers.js'
9 |
10 | /**
11 | * @description Transfer ownership of input contract and wait until corresponding transaction is mined
12 | * @param contract {Object} - Truffle Contract Object
13 | * @param controller {String}
14 | * @param newController {String}
15 | * @returns transaction receipt {Object}
16 | */
17 | const transferControl = async (contract, controller, newController) => {
18 | let params = { from: controller, gas: gas }
19 | let txn = await contract.transferControl(newController, params)
20 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
21 | return txnReceipt
22 | }
23 |
24 | /**
25 | * @description Transfer the ownerships of input contracts and wait until corresponding transactions are mined
26 | * @param contracts {Object} - Truffle Object Contract Array
27 | * @param controller {String}
28 | * @param newController {String}
29 | */
30 | const transferControls = async (contracts, controller, newController) => {
31 | let promises = contracts.map(function (contract) { transferControl(contract, controller, newController) })
32 | await Promise.all(promises)
33 | }
34 |
35 | /**
36 | * @description Lock ownership of input contract and wait until corresponding transaction is mined
37 | * @param contract {Object} - Truffle Object Contract Array
38 | * @param controller - {String}
39 | * @returns Transaction Receipt {Object}
40 | */
41 | const lockControl = async (contract, controller) => {
42 | let params = { from: controller, gas: gas }
43 | let txn = await contract.lockControl(controller, params)
44 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
45 | return txnReceipt
46 | }
47 |
48 | module.exports = {
49 | transferControl,
50 | transferControls,
51 | lockControl
52 | }
53 |
--------------------------------------------------------------------------------
/scripts/disableTransfers.js:
--------------------------------------------------------------------------------
1 | module.exports = async function (callback) {
2 | require('babel-register')
3 | require('babel-polyfill')
4 | require('./jsHelpers.js')
5 |
6 | const Web3 = require('web3')
7 | const ProofToken = artifacts.require('./ProofToken.sol')
8 | const TokenSale = artifacts.require('./TokenSale.sol')
9 | const provider = artifacts.options.provider
10 | const web3 = new Web3(provider)
11 | const config = require('../config')
12 |
13 | let tokenSale
14 | let sender
15 |
16 | web3.eth.getAccounts(function(error,result) {
17 | let sender = result[0]
18 | run(sender)
19 | callback()
20 | })
21 |
22 | const run = async function(sender) {
23 | tokenSale = await TokenSale.deployed()
24 | let txn = await tokenSale.enableTransfers(false, { from: sender, gas: config.constants.DEFAULT_GAS, gasPrice: config.constants.DEFAULT_GAS_PRICE })
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/scripts/enableTransfers.js:
--------------------------------------------------------------------------------
1 | module.exports = async function (callback) {
2 |
3 | require('babel-register')
4 | require('babel-polyfill')
5 | require('./jsHelpers.js')
6 |
7 | const Web3 = require('web3')
8 | const ProofToken = artifacts.require('./ProofToken.sol')
9 | const TokenSale = artifacts.require('./TokenSale.sol')
10 | const provider = artifacts.options.provider
11 | const web3 = new Web3(provider)
12 | const config = require('../config')
13 |
14 | let tokenSale
15 | let sender
16 |
17 | web3.eth.getAccounts(function(error,result) {
18 | let sender = result[0]
19 | run(sender)
20 | callback("Success")
21 | })
22 |
23 | const run = async function(sender) {
24 | tokenSale = await TokenSale.deployed()
25 | let txn = await tokenSale.enableTransfers(true, { from: sender, gas: config.constants.DEFAULT_GAS, gasPrice: config.constants.DEFAULT_GAS_PRICE })
26 | }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/scripts/getPresaleBalances.js:
--------------------------------------------------------------------------------
1 | module.exports = async function(callback) {
2 |
3 | const csv = require('csv-parser')
4 | const json2csv = require('json2csv')
5 | const Web3 = require('web3')
6 |
7 | const fs = require('fs')
8 | const request = require('async-request')
9 | const csvdata = require('csvdata')
10 | const awaitEach = require('await-each')
11 |
12 | let config = require('../config')
13 | let getTokenBalance = require('./tokenHelpers').getTokenBalance
14 |
15 | let presaleToken = config.addresses.ethereum.PRESALE_TOKEN
16 |
17 | const ProofPresaleToken = artifacts.require('./ProofPresaleToken.sol')
18 | const proofPresaleToken = await ProofPresaleToken.at(presaleToken)
19 | const provider = artifacts.options.provider
20 | const web3 = new Web3(provider)
21 |
22 | let addresses = [];
23 | var balances = [];
24 |
25 | const writeData = new Promise((resolve, reject) => {
26 | fs.createReadStream('./scripts/addresses.csv')
27 | .pipe(csv())
28 | .on('data', function(data) {
29 | addresses.push(data['Addresses'])
30 | })
31 | .on('end', resolve);
32 | })
33 |
34 | const getBalance = async(address) => {
35 | let balance = await getTokenBalance(proofPresaleToken, address)
36 | return { "address": address, "balance": balance }
37 | }
38 |
39 | async function run() {
40 | await writeData;
41 |
42 | let tokenBalances = await awaitEach(addresses, async function(address) {
43 | return await getBalance(address);
44 | })
45 |
46 | let fields = ['address', 'balance'];
47 | let csv = json2csv({ data: tokenBalances, fields: fields })
48 |
49 | fs.writeFile('./balances.csv', csv, function(err) {
50 | if (err) throw err;
51 | console.log('file saved');
52 | });
53 |
54 | };
55 |
56 | run();
57 | }
58 |
--------------------------------------------------------------------------------
/scripts/helpers.js:
--------------------------------------------------------------------------------
1 | import moment from 'moment'
2 |
3 | /**
4 | * @module Helpers
5 | */
6 |
7 | var Promise = require('bluebird')
8 | let chai = require('chai')
9 | var chaiAsPromised = require('chai-as-promised')
10 | const expect = chai.expect
11 | chai.should()
12 | chai.use(chaiAsPromised)
13 |
14 | /**
15 | * @description Returns a promise that is resolve when transactions corresponding to input hashes are resolved
16 | * @param txnHashes {String[]}
17 | * @returns Promise resolved upon mining of all input transaction {Promise}
18 | */
19 | const waitUntilTransactionsMined = (txnHashes) => {
20 | var transactionReceiptAsync
21 | const interval = 500
22 | transactionReceiptAsync = function (txnHashes, resolve, reject) {
23 | try {
24 | var receipt = web3.eth.getTransactionReceipt(txnHashes)
25 | if (receipt == null) {
26 | setTimeout(function () {
27 | transactionReceiptAsync(txnHashes, resolve, reject)
28 | }, interval)
29 | } else {
30 | resolve(receipt)
31 | }
32 | } catch (e) {
33 | reject(e)
34 | }
35 | }
36 |
37 | if (Array.isArray(txnHashes)) {
38 | var promises = []
39 | txnHashes.forEach(function (txnHash) {
40 | promises.push(waitUntilTransactionsMined(txnHash))
41 | })
42 | return Promise.all(promises)
43 | } else {
44 | return new Promise(function (resolve, reject) { transactionReceiptAsync(txnHashes, resolve, reject) })
45 | }
46 | }
47 |
48 | /**
49 | * @description Returns the balance of an ethereum wallet
50 | * @param address {String} - Ethereum address
51 | * @returns wallet balance {Number}
52 | */
53 | const getBalance = (address) => {
54 | let balance = web3.eth.getBalance(address)
55 | return balance.toNumber()
56 | }
57 |
58 | /**
59 | * @description Returns the balance of several ethereum wallets (in wei)
60 | * @param addresses {String[]} - Array of ethereum addresses
61 | * @returns wallet balances (in wei) {Number[]}
62 | */
63 | const getBalances = (addresses) => {
64 | let balances = []
65 | addresses.map(function (address) { balances.push(getBalance(address)) })
66 | return balances
67 | }
68 |
69 | /**
70 | * @description Returns the balance of an ethereum wallet (in ether)
71 | * @param address {String} - Ethereum address
72 | * @returns wallet balance (in ether) {Number}
73 | */
74 | const getEtherBalance = (address) => {
75 | let balance = web3.fromWei(web3.eth.getBalance(address), 'ether')
76 | return balance.toNumber()
77 | }
78 |
79 | /**
80 | * @description Returns the balance of several ethereum wallets (in ether)
81 | * @param addresses {String[]}
82 | * @returns wallet balances (in ether) {Number[]}
83 | */
84 | const getEtherBalances = (addresses) => {
85 | let balances = []
86 | addresses.forEach(function (address) { balances.push(getEtherBalance(address)) })
87 | return balances
88 | }
89 |
90 | /**
91 | * @description Converts wei to ether
92 | * @param valueInWei {Number}
93 | * @returns valueInEther {Number}
94 | */
95 | const inEther = (valueInWei) => {
96 | let amount = web3.fromWei(valueInWei, 'ether')
97 | return Number(amount)
98 | }
99 |
100 | /**
101 | * @description Converts ether to wei
102 | * @param valueInEther {Number}
103 | * @returns valueInWei {Number}
104 | */
105 | const inWei = (valueInEther) => {
106 | let amount = web3.toWei(valueInEther, 'ether')
107 | return amount.toNumber()
108 | }
109 |
110 | // in our case the base units are cents
111 | /**
112 | * @description Convert tokens cents to token units
113 | * @param tokenCents {Number}
114 | * @returns token base units {Number}
115 | */
116 | const inBaseUnits = (tokenCents) => {
117 | return tokenCents / (10 ** 2)
118 | }
119 |
120 | /**
121 | * @description Converts token units to token cents
122 | * @param tokenBaseUnits {Number}
123 | * @returns token cents {Number}
124 | */
125 | const inCents = (tokenBaseUnits) => {
126 | return tokenBaseUnits * (10 ** 2)
127 | }
128 |
129 | /**
130 | * @description Converts token base units (ERC20 units) to token units
131 | * @param tokenBaseUnits {Number}
132 | * @returns token units {Number}
133 | */
134 | const inTokenUnits = (tokenBaseUnits) => {
135 | return tokenBaseUnits / (10 ** 18)
136 | }
137 |
138 | /**
139 | * @description Returns address corresponding to a contract
140 | * @param contract {Object} - Truffle Contract Object
141 | * @returns address {String}
142 | */
143 | const getAddress = async (contract) => {
144 | let address = contract.address
145 | return address
146 | }
147 |
148 | /**
149 | * @description Returns the addresses corresponding to an array of contracts
150 | * @param contracts {Object} Array of truffle contract objects
151 | * @returns address[] {String[]}
152 | */
153 | const getAddresses = async (contracts) => {
154 | let addresses = contracts.map(function (contract) {
155 | return contract.address
156 | })
157 | return addresses
158 | }
159 |
160 | /**
161 | * @description Send an ethereum transaction and wait until the transaction is mined
162 | * @param txn {Object} Web3 transaction object
163 | * @returns txnReceipt {Object} transaction receipt
164 | */
165 | const sendTransaction = async (txn) => {
166 | let txnHash = await web3.eth.sendTransaction(txn)
167 | let txnReceipt = await waitUntilTransactionsMined(txnHash)
168 | return txnReceipt
169 | }
170 |
171 | /**
172 | * @description Send ethereum transactions and wait until all transactions are mined
173 | * @param txns {Object} Web3 transactions object
174 | * @returns txnReceipts {Object} transaction receipts
175 | */
176 | const sendTransactions = async (txns) => {
177 | let txnHashes = []
178 | let txnHash
179 |
180 | for (let txn of txns) {
181 | txnHash = await sendTransaction(txn)
182 | txnHashes.push(txnHash)
183 | }
184 |
185 | return txnHashes
186 | }
187 |
188 | /**
189 | * @description Fails if the input promise is not rejected with an Invalid opcode message
190 | * @param promise
191 | */
192 | const expectInvalidOpcode = async (promise) => {
193 | try {
194 | await promise
195 | } catch (error) {
196 | expect(error.message).to.include('invalid opcode')
197 | return
198 | }
199 | expect.fail('Expected throw not received')
200 | }
201 |
202 | /**
203 | * @description Fails if the input promise is not reject with an Invalid jump message
204 | * @param promise
205 | */
206 | const expectInvalidJump = async (promise) => {
207 | try {
208 | await promise
209 | } catch (error) {
210 | expect(error.message).to.include('invalid JUMP')
211 | return
212 | }
213 | expect.fail('Expected throw not received')
214 | }
215 |
216 | /**
217 | * @description Fails if the input promise is not rejected with an Out of Gas message
218 | * @param promise
219 | */
220 | const expectOutOfGas = async (promise) => {
221 | try {
222 | await promise
223 | } catch (error) {
224 | expect(error.message).to.include('out of gas')
225 | return
226 | }
227 | expect.fail('Expected throw not received')
228 | }
229 |
230 | /**
231 | * @description Mine the local evm
232 | * @returns promise
233 | */
234 | const advanceBlock = () => {
235 | return new Promise((resolve, reject) => {
236 | web3.currentProvider.sendAsync({
237 | jsonrpc: '2.0',
238 | method: 'evm_mine',
239 | id: Date.now(),
240 | }, (err, res) => {
241 | return err ? reject(err) : resolve(err)
242 | })
243 | })
244 | }
245 |
246 | /**
247 | * @description Advance to input block
248 | * @param number
249 | */
250 | const advanceToBlock = async(number) => {
251 | if (web3.eth.blockNumber > number) {
252 | throw Error(`block number ${number} is in the past (current is ${web3.eth.blockNumber})`)
253 | }
254 | while (web3.eth.blockNumber < number) {
255 | await advanceBlock()
256 | }
257 | }
258 |
259 | const latestTime = function() {
260 | return moment.unix(web3.eth.getBlock('latest').timestamp)
261 | }
262 |
263 | const increaseTime = function(duration) {
264 | const id = Date.now()
265 |
266 | return new Promise((resolve, reject) => {
267 | web3.currentProvider.sendAsync({
268 | jsonrpc: '2.0',
269 | method: 'evm_increaseTime',
270 | params: [duration.asSeconds()],
271 | id: id,
272 | }, err1 => {
273 | if (err1) return reject(err1)
274 |
275 | web3.currentProvider.sendAsync({
276 | jsonrpc: '2.0',
277 | method: 'evm_mine',
278 | id: id+1,
279 | }, (err2, res) => {
280 | return err2 ? reject(err2) : resolve(res)
281 | })
282 | })
283 | })
284 | }
285 |
286 | const getTxnReceiptData = (txnReceipt) => {
287 | let logs = txnReceipt.logs
288 | let dataArray = []
289 | logs.forEach(log => {
290 | let data = log.data
291 | if (data) {
292 | dataArray.push(data)
293 | } else {
294 | dataArray.push('no data')
295 | }
296 | })
297 |
298 | return dataArray
299 | }
300 |
301 | const getTxnReceiptTopics = (txnReceipt) => {
302 | let logs = txnReceipt.logs
303 |
304 | let topics = logs.map(log => {
305 | let topics = log.topics
306 | let result = {
307 | 'functionID': topics[0],
308 | 'parameters': topics.slice(1)
309 | }
310 | return result
311 | })
312 | return topics
313 | }
314 |
315 | module.exports = {
316 | waitUntilTransactionsMined,
317 | getBalance,
318 | getBalances,
319 | getEtherBalance,
320 | getEtherBalances,
321 | inEther,
322 | inWei,
323 | inBaseUnits,
324 | inTokenUnits,
325 | inCents,
326 | getAddress,
327 | getAddresses,
328 | sendTransaction,
329 | sendTransactions,
330 | expectInvalidOpcode,
331 | expectInvalidJump,
332 | expectOutOfGas,
333 | advanceToBlock,
334 | getTxnReceiptData,
335 | getTxnReceiptTopics,
336 | latestTime,
337 | increaseTime
338 | }
339 |
340 |
--------------------------------------------------------------------------------
/scripts/importBalances.js:
--------------------------------------------------------------------------------
1 | module.exports = async function (callback) {
2 |
3 | Array.prototype.toNumber = function () {
4 | return this.map((elem) => { return parseFloat(elem) })
5 | }
6 |
7 | require('babel-register')
8 | require('babel-polyfill')
9 | require('./jsHelpers.js')
10 |
11 | const fs = require('fs')
12 | const csv = require('csv-parser')
13 | const Web3 = require('web3')
14 | const config = require('../config.js')
15 |
16 | const ProofPresaleToken = artifacts.require('./ProofPresaleToken.sol')
17 | const ProofToken = artifacts.require('./ProofToken.sol')
18 | const provider = artifacts.options.provider
19 | const web3 = new Web3(provider)
20 |
21 | let proofToken
22 | let proofPresaleToken
23 | let fund
24 |
25 | web3.eth.getAccounts(function(error,result) {
26 | fund = result[0]
27 | })
28 |
29 |
30 | const getAddress = async (contract) => {
31 | let address = contract.address
32 | return address
33 | }
34 |
35 | const importBalances = async(token, caller, addresses, balances) => {
36 | let txn = await token.importPresaleBalances(addresses, balances, { from: caller, gas: config.constants.MAX_GAS, gasPrice: config.constants.DEFAULT_HIGH_GAS_PRICE })
37 | }
38 |
39 | const run = async function(){
40 | proofToken = await ProofToken.deployed()
41 | await launchImport()
42 | }
43 |
44 | const launchImport = async function() {
45 | let addresses = []
46 | let balances = []
47 |
48 | const writeData = new Promise((resolve, reject) => {
49 | fs.createReadStream('./scripts/balances.csv')
50 | .pipe(csv())
51 | .on('data', function (data) {
52 | addresses.push(data['address'])
53 | balances.push(data['balance'])
54 | })
55 | .on('end', resolve)
56 | })
57 |
58 | await writeData
59 | balances = balances.toNumber()
60 |
61 | let addressListNumber = addresses.length
62 |
63 | for (let i = 0; i < addressListNumber; i = i + 50) {
64 | let addressesBatch = addresses.slice(i, i + 50)
65 | let balancesBatch = balances.slice(i, i + 50)
66 | let receipt = await importBalances(proofToken, fund, addressesBatch, balancesBatch)
67 | }
68 | }
69 |
70 | await run()
71 | callback()
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/scripts/jsHelpers.js:
--------------------------------------------------------------------------------
1 | Array.prototype.toNumber = function () {
2 | return this.map((elem) => { return parseInt(elem) })
3 | }
4 | Array.prototype.sum = function () {
5 | return this.reduce((pv, cv) => pv + cv, 0)
6 | }
7 |
--------------------------------------------------------------------------------
/scripts/lockBalances.js:
--------------------------------------------------------------------------------
1 | module.exports = async function (callback) {
2 |
3 | require('babel-register')
4 | require('babel-polyfill')
5 | require('./jsHelpers.js')
6 |
7 | const Web3 = require('web3')
8 | const ProofToken = artifacts.require('./ProofToken.sol')
9 | const provider = artifacts.options.provider
10 | const web3 = new Web3(provider)
11 | const config = require('../config')
12 |
13 | let proofToken
14 | let sender
15 |
16 | web3.eth.getAccounts(function(error,result) {
17 | let sender = result[0]
18 | run(sender)
19 | callback()
20 | })
21 |
22 | const run = async function(sender) {
23 | proofToken = await ProofToken.deployed()
24 | let txn = await proofToken.lockPresaleBalances({ from: sender, gas: config.constants.DEFAULT_GAS, gasPrice: config.constants.DEFAULT_HIGH_GAS_PRICE })
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/scripts/logEvents.js:
--------------------------------------------------------------------------------
1 | module.exports = async function (callback) {
2 |
3 | require('babel-register')
4 | require('babel-polyfill')
5 | require('./jsHelpers.js')
6 |
7 | const Web3 = require('web3')
8 | const provider = artifacts.options.provider
9 | const web3 = new Web3(provider)
10 |
11 | const ProofToken = artifacts.require('./ProofToken.sol')
12 | const TokenSale = artifacts.require('./TokenSale.sol')
13 |
14 | const proofToken = await ProofToken.deployed()
15 | const proofTokenSale = await TokenSale.deployed()
16 |
17 | let tokenEvents = proofToken.allEvents({fromBlock: 1047310, toBlock: 'latest'})
18 | let tokenSaleEvents = proofTokenSale.allEvents({fromBlock: 0, toBlock: 'latest'})
19 |
20 | tokenEvents.watch((err,res) => {
21 | console.log("\n****************\n")
22 | console.log(res)
23 | console.log("\n****************\n")
24 | })
25 |
26 | tokenSaleEvents.watch((err,res) => {
27 | console.log("\n****************\n")
28 | console.log(res)
29 | console.log("\n****************\n")
30 | })
31 |
32 | callback()
33 | }
--------------------------------------------------------------------------------
/scripts/ownershipHelpers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Ownership helpers module
3 | * @module ownership-helpers
4 | */
5 |
6 | var Promise = require('bluebird')
7 | import { gas } from './testConfig.js'
8 | import { waitUntilTransactionsMined } from './helpers.js'
9 |
10 | /**
11 | * @description Transfer ownership of input contract and wait until corresponding transaction is mined
12 | * @param contract {Object} - Truffle Contract Object
13 | * @param sender {String}
14 | * @param receiver {String}
15 | * @returns transaction receipt {Object}
16 | */
17 | const transferOwnership = async (contract, sender, receiver) => {
18 | let params = { from: sender, gas: gas }
19 | let txn = await contract.transferOwnership(receiver, params)
20 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
21 | return txnReceipt
22 | }
23 |
24 | /**
25 | * @description Transfer the ownerships of input contracts and wait until corresponding transactions are mined
26 | * @param contracts {Object} - Truffle Object Contract Array
27 | * @param sender {String}
28 | * @param receiver {String}
29 | */
30 | const transferOwnerships = async (contracts, sender, receiver) => {
31 | let promises = contracts.map(function (contract) { transferOwnership(contract, sender, receiver) })
32 | await Promise.all(promises)
33 | }
34 |
35 | /**
36 | * @description Lock ownership of input contract and wait until corresponding transaction is mined
37 | * @param contract {Object} - Truffle Object Contract Array
38 | * @param owner - {String}
39 | * @returns Transaction Receipt {Object}
40 | */
41 | const lockOwnership = async (contract, owner) => {
42 | let params = { from: owner, gas: gas }
43 | let txn = await contract.lockOwnership(owner, params)
44 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
45 | return txnReceipt
46 | }
47 |
48 | module.exports = {
49 | transferOwnership,
50 | transferOwnerships,
51 | lockOwnership
52 | }
53 |
--------------------------------------------------------------------------------
/scripts/pausableHelpers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Pausable helpers module
3 | * @module pausable-helpers
4 | */
5 |
6 | import { waitUntilTransactionsMined } from './helpers.js'
7 |
8 | /**
9 | * @description Pause the contract and wait until the transaction is mined
10 | * @param contract Token truffle contract
11 | * @param owner Ethereum Address
12 | */
13 | const pause = async(contract, owner) => {
14 | let tx = await contract.pause({ from: owner, gas: 1000000 })
15 | await waitUntilTransactionsMined(tx.tx)
16 | }
17 |
18 | /**
19 | * @description Unpause contract and wait until the transaction is mined
20 | * @param contract Token Truffle Contract
21 | * @param owner Ethereum Address
22 | */
23 | const unpause = async(contract, owner) => {
24 | let tx = await contract.unpause({ from :owner, gas: 1000000 })
25 | await waitUntilTransactionsMined(tx.tx)
26 | }
27 |
28 | module.exports = {
29 | pause,
30 | unpause
31 | }
32 |
--------------------------------------------------------------------------------
/scripts/testConfig.js:
--------------------------------------------------------------------------------
1 | const DEFAULT_GAS = 2 * 10 ** 6
2 | const MAX_GAS = 4.7 * 10 ** 6
3 | const DEFAULT_LOW_GAS_PRICE = 2 * 10 ** 9
4 | const DEFAULT_GAS_PRICE = 6 * 10 ** 9
5 | const DEFAULT_HIGH_GAS_PRICE = 40 * 10 ** 9
6 | const TOKENS_ALLOCATED_TO_PROOF = 1181031 * (10 ** 18)
7 | const DECIMALS_POINTS = 10 ** 18
8 | const TOKEN_UNITS = 10 ** 18
9 |
10 | const WALLET_ADDRESS = '0xe2b3204f29ab45d5fd074ff02ade098fbc381d42'
11 | const PROOF_WALLET_ADDRESS = '0xe2b3204f29ab45d5fd074ff02ade098fbc381d42'
12 |
13 | const pointsMultiplier = 10 ** 18
14 | const ether = 10 ** 18
15 |
16 | module.exports = {
17 | DEFAULT_GAS,
18 | MAX_GAS,
19 | DEFAULT_LOW_GAS_PRICE,
20 | DEFAULT_GAS_PRICE,
21 | DEFAULT_HIGH_GAS_PRICE,
22 | TOKEN_UNITS,
23 | DECIMALS_POINTS,
24 | TOKENS_ALLOCATED_TO_PROOF,
25 | PROOF_WALLET_ADDRESS,
26 | WALLET_ADDRESS,
27 | ether,
28 | pointsMultiplier
29 | }
30 |
--------------------------------------------------------------------------------
/scripts/tokenHelpers.js:
--------------------------------------------------------------------------------
1 | const h = require('../scripts/helpers.js')
2 | const config = require('../config.js')
3 | import { getAddress } from './helpers.js'
4 |
5 | let { DEFAULT_GAS, DEFAULT_GAS_PRICE, MAX_GAS } = config.constants;
6 |
7 | /**
8 | * @description Get owner of token contract
9 | * @param token
10 | * @returns owner
11 | */
12 | const getOwner = async (token) => {
13 | let owner = await token.owner.call()
14 | return owner
15 | }
16 |
17 | /**
18 | * @description Get owner of token contract
19 | * @param token
20 | * @returns owner
21 | */
22 | const getController = async (token) => {
23 | let controller = await token.controller.call()
24 | return controller
25 | }
26 |
27 | /**
28 | * @description Get total supply of token contract
29 | * @param token
30 | * @returns total supply
31 | */
32 | const getTotalSupply = async (token) => {
33 | let tokenSupply = await token.totalSupply.call()
34 | return tokenSupply.toNumber()
35 | }
36 |
37 | /**
38 | * @description Get total supply of token contract
39 | * @param token
40 | * @returns total supply
41 | */
42 | const getTotalSupplyAt = async (token, blockNumber) => {
43 | let tokenSupply = await token.totalSupplyAt.call(blockNumber)
44 | return tokenSupply.toNumber()
45 | }
46 |
47 | /**
48 | * @description Get token balance of owner
49 | * @param token
50 | * @param owner
51 | * @returns token balance
52 | */
53 | const getTokenBalance = async (token, owner) => {
54 | let balance = await token.balanceOf.call(owner)
55 | return balance.toNumber()
56 | }
57 |
58 | /**
59 | * @description Get token balance of owner
60 | * @param token
61 | * @param owner
62 | * @returns token balance
63 | */
64 | const getTokenBalanceAt = async (token, owner, blockNumber) => {
65 | let balance = await token.balanceOfAt.call(owner, blockNumber)
66 | return balance.toNumber()
67 | }
68 |
69 |
70 | /**
71 | * @description Transfer amount of token from sender to receiver
72 | * @param token
73 | * @param sender
74 | * @param receiver
75 | * @param amount
76 | * @returns transaction receipt
77 | */
78 | const transferToken = async(token, sender, receiver, amount) => {
79 | let params = { from: sender, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
80 | let txn = await token.transfer(receiver, amount, params)
81 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
82 | return txnReceipt
83 | }
84 |
85 | /**
86 | * @description Transfer amount of token from sender to receiver
87 | * @param token
88 | * @param caller
89 | * @param receiver
90 | * @param amount
91 | * @returns transaction receipt
92 | */
93 | const transferTokenFrom = async(token, caller, sender, receiver, amount) => {
94 | let params = { from: caller, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
95 | let txn = await token.transferFrom(sender, receiver, amount, params)
96 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
97 | return txnReceipt
98 | }
99 |
100 | /**
101 | * @description Transfer amount of each token in the tokens array from sender to receiver
102 | * @param token
103 | * @param sender
104 | * @param receiver
105 | * @param amount
106 | * @returns transaction receipts
107 | */
108 | const transferTokens = async(tokens, sender, receiver, amount) => {
109 | let promises = tokens.map(function (oneToken) { transferToken(oneToken, sender, receiver, amount) })
110 | let txnReceipts = await Promise.all(promises)
111 | return txnReceipts
112 | }
113 |
114 | /**
115 | * @description Mint amount of token for the receiver. Only works if minter is the owner of the token
116 | * @param contract
117 | * @param minter
118 | * @param receiver
119 | * @param amount
120 | * @returns transaction receipt
121 | */
122 | const mintToken = async(contract, minter, receiver, amount) => {
123 | let params = { from: minter, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
124 | let txn = await contract.mint(receiver, amount, params)
125 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
126 | return txnReceipt
127 | }
128 |
129 | /**
130 | * @description Finish minting period for the token contract. Only works if sender is the owner of the token
131 | * @param token
132 | * @param sender
133 | * @returns transaction receipt
134 | */
135 | const finishMinting = async(token, sender) => {
136 | let params = { from: sender, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
137 | let txn = await token.finishMinting(params)
138 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
139 | return txnReceipt
140 | }
141 |
142 | /**
143 | * @description Burn amount of tokens from the owner
144 | * @param contract
145 | * @param minter
146 | * @param receiver
147 | * @param amount
148 | * @returns transaction receipt
149 | */
150 | const burnTokens = async(contract, caller, owner, amount) => {
151 | let params = { from: caller, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
152 | let txn = await contract.burn(owner, amount, params)
153 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
154 | return txnReceipt
155 | }
156 |
157 | /**
158 | * @description Convert ERC20 units (=number of base units times 10^decimals) to base units
159 | * @param token
160 | * @param amount
161 | * @returns base units
162 | */
163 | const baseUnits = async(token, amount) => {
164 | let decimals = await token.decimals.call()
165 | return (amount / (10 ** decimals.toNumber()))
166 | }
167 |
168 | /**
169 | * @description Convert base units (=number of ERC20 units divided by 10^decimals) to ERC20 units
170 | * @param token
171 | * @param amount
172 | * @returns ERC20 units
173 | */
174 | const ERC20Units = async(token, amount) => {
175 | let decimals = await token.decimals.call()
176 | return (amount * (10 ** decimals.toNumber()))
177 | }
178 |
179 | /**
180 | * @description Allocates (presale) tokens to the sender
181 | * @param token
182 | * @param sender
183 | * @returns transaction receipt
184 | */
185 | const claimTokens = async(token, sender) => {
186 | let params = { from: sender, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
187 | let txn = await token.claimTokens(params)
188 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
189 | return txnReceipt
190 | }
191 |
192 | /**
193 | * @description Import presale tokens to the token sale contract
194 | * @param token
195 | * @param addresses
196 | * @param balances
197 | * @returns transaction receipt
198 | */
199 | const importBalances = async(token, caller, addresses, balances) => {
200 | let txn = await token.importPresaleBalances(addresses, balances, { from: caller, gas: MAX_GAS, gasPrice: DEFAULT_GAS_PRICE })
201 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
202 | return txnReceipt
203 | }
204 |
205 | const lockBalances = async(token, caller) => {
206 | let txn = await token.lockPresaleBalances({ from: caller })
207 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
208 | return txnReceipt
209 | }
210 |
211 | const cloneToken = async(contract, caller, config) => {
212 | let txn = await contract.createCloneToken(
213 | config.block,
214 | config.name,
215 | config.symbol,
216 | { from: caller })
217 |
218 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
219 | return txnReceipt
220 | }
221 |
222 | const approve = async(token, caller, spender, amount) => {
223 | let txn = await token.approve(spender, amount, {from: caller })
224 | let txnReceipt = await h.waitUntilTransactionsMined(txn.tx)
225 | return txnReceipt
226 | }
227 |
228 | const getAllowance = async(token, owner, spender) => {
229 | let allowance = await token.allowance.call(owner, spender)
230 | return allowance.toNumber()
231 | }
232 |
233 | const enableTransfers = async(token, caller) => {
234 | let txn = await token.enableTransfers(true, { from: caller })
235 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
236 | }
237 |
238 | const lockTransfers = async(token, caller) => {
239 | let txn = await token.enableTransfers(false, { from: caller })
240 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
241 | }
242 |
243 | module.exports = {
244 | getOwner,
245 | getController,
246 | getTotalSupply,
247 | getTotalSupplyAt,
248 | getTokenBalance,
249 | getTokenBalanceAt,
250 | transferToken,
251 | transferTokenFrom,
252 | transferTokens,
253 | mintToken,
254 | burnTokens,
255 | finishMinting,
256 | baseUnits,
257 | ERC20Units,
258 | claimTokens,
259 | importBalances,
260 | lockBalances,
261 | cloneToken,
262 | approve,
263 | getAllowance
264 | }
265 |
--------------------------------------------------------------------------------
/scripts/tokenSaleHelpers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Token Sale Helpers Module
3 | * @module token-sale-helpers
4 | */
5 |
6 | import { DEFAULT_GAS, DEFAULT_GAS_PRICE, ether, pointsMultiplier } from './testConfig.js'
7 | import { waitUntilTransactionsMined } from './helpers.js'
8 |
9 | /**
10 | * @description Returns wallet address for input token sale contract
11 | * @alias module:token-sale-helpers
12 | * @param tokenSale {Object} - Truffle Contract Object
13 | * @returns wallet {String}
14 | */
15 | const getWallet = async (tokenSale) => {
16 | let wallet = await tokenSale.wallet.call()
17 | return wallet
18 | }
19 |
20 | const getMultisig = async (tokenSale) => {
21 | let multisig = await tokenSale.proofMultiSig.call()
22 | return multisig
23 | }
24 |
25 | const getContributors = async (tokenSale) => {
26 | let contributors = await tokenSale.contributors.call()
27 | return contributors.toNumber()
28 | }
29 |
30 | /**
31 | * @description Returns token address for input token sale contract
32 | * @alias module:token-sale-helpers
33 | * @param tokenSale {Object} - Truffle Contract Object
34 | * @returns token {String}
35 | */
36 | const getToken = async (tokenSale) => {
37 | let token = await tokenSale.proofToken.call()
38 | return token
39 | }
40 |
41 | /**
42 | * @description Returns presale token for input token sale contract
43 | * @alias module:token-sale-helpers
44 | * @param tokenSale {Object} - Truffle Contract Object
45 | * @returns token {String}
46 | */
47 | const getPresaleToken = async (tokenSale) => {
48 | let presaleToken = await tokenSale.proofPresaleToken.call()
49 | return presaleToken
50 | }
51 |
52 | /**
53 | * @description Returns cap for input token sale contract
54 | * @alias module:token-sale-helpers
55 | * @param tokenSale {Object} - Truffle Contract Object
56 | * @returns token sale cap {String}
57 | */
58 | const getCap = async (tokenSale) => {
59 | let cap = await tokenSale.cap.call()
60 | return cap.toNumber()
61 | }
62 |
63 | /**
64 | * @description Returns the price in wei of one token sold by the input token sale contract
65 | * @alias module:token-sale-helpers
66 | * @param tokenSale {Object} - Truffle Contract Object
67 | * @returns token price in wei {String}
68 | */
69 | const getBasePriceInWei = async (tokenSale) => {
70 | let priceInWei = await tokenSale.BASE_PRICE_IN_WEI.call()
71 | return priceInWei.toNumber()
72 | }
73 |
74 | /**
75 | * @description Returns the base token price (price of the token without current premium)
76 | * @alias module:token-sale-helpers
77 | * @param tokenSale {Object} - Truffle Contract Object
78 | * @returns base token price in wei {Number}
79 | */
80 | const getBasePrice = async (tokenSale) => {
81 | let price = await getBasePriceInWei(tokenSale)
82 | return (price / 10 ** 18)
83 | }
84 |
85 | /**
86 | * @description Returns token price in wei
87 | * @alias module:token-sale-helpers
88 | * @param tokenSale {Object} - Truffle Contract Object
89 | * @returns token price in wei {Number}
90 | */
91 | const getPriceInWei = async (tokenSale) => {
92 | let priceInWei = await tokenSale.getPriceInWei.call()
93 | return priceInWei.toNumber()
94 | }
95 |
96 | /**
97 | * @description Returns token price in ether
98 | * @alias module:token-sale-helpers
99 | * @param tokenSale {Object} - Truffle Contract Object
100 | * @returns token price in ether {Number}
101 | */
102 | const getPrice = async (tokenSale) => {
103 | let price = await getPriceInWei(tokenSale)
104 | return (price / 10 ** 18)
105 | }
106 |
107 | /**
108 | * @description Returns the number of remaining tokens
109 | * @alias module:token-sale-helpers
110 | * @param tokenSale {Object} - Truffle Contract Object
111 | * @returns remaining tokens
112 | */
113 | const getRemainingTokens = async (tokenSale) => {
114 | let remainingTokens = await tokenSale.remainingTokens.call()
115 | return remainingTokens.toNumber()
116 | }
117 |
118 | /**
119 | * @description Performs an token order from sender to the input token sale contract
120 | * @alias module:token-sale-helpers
121 | * @param tokenSale {Object} - Truffle Contract Object corresponding to token sale contract
122 | * @param sender {String} - Ethereum address from which ether is being sent
123 | * @param value {Number} - Value to be send to the contract
124 | * @returns txnReceipt {Object} - Transaction receipt
125 | */
126 | const buyTokens = async (tokenSale, sender, value) => {
127 | let order = {
128 | from: sender,
129 | value: value,
130 | gas: DEFAULT_GAS,
131 | gasPrice: DEFAULT_GAS_PRICE
132 | }
133 |
134 | let txn = await tokenSale.buyTokens(sender, order)
135 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
136 | return txnReceipt
137 | }
138 |
139 | /**
140 | * @description Returns the token price in wei
141 | * @alias module:token-sale-helpers
142 | * @param tokenSale {Object} - Truffle Contract Object
143 | * @returns token price in wei {Number}
144 | */
145 | const tokenPriceInWei = async (tokenSale) => {
146 | let price = await tokenSale.getPriceInWei.call()
147 | return price.toNumber()
148 | }
149 |
150 | /**
151 | * @description Returns the token price
152 | * @alias module:token-sale-helpers
153 | * @param tokenSale {Object} - Truffle Contract Object
154 | * @returns token price in ether {Number}
155 | */
156 | const tokenPrice = async (tokenSale) => {
157 | let price = await getPriceInWei(tokenSale)
158 | return (price.toNumber() / ether)
159 | }
160 |
161 | /**
162 | * @description Returns number of tokens for a certain amount of ether sent to a token sale contract
163 | * @alias module:token-sale-helpers
164 | * @param tokenSale {Object} - Truffle Contract Object
165 | * @param weiAmount {Number}
166 | * @returns number of tokens {Number}
167 | */
168 | const numberOfTokensFor = async (tokenSale, weiAmount) => {
169 | let priceInWei = await tokenPriceInWei(tokenSale)
170 | let numberOfTokens = Math.floor(weiAmount * pointsMultiplier / priceInWei)
171 | return numberOfTokens
172 | }
173 |
174 | const finalize = async (tokenSale, caller) => {
175 | let txn = await tokenSale.finalize({ from: caller })
176 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
177 | return txnReceipt
178 | }
179 |
180 | const enableTransfers = async (tokenSale, caller) => {
181 | let txn = await tokenSale.enableTransfers({ from: caller })
182 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
183 | return txnReceipt
184 | }
185 |
186 | const lockTransfers = async (tokenSale, caller) => {
187 | let txn = await tokenSale.lockTransfers({ from: caller })
188 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
189 | return txnReceipt
190 | }
191 |
192 | const enableMasterTransfers = async (tokenSale, caller) => {
193 | let txn = await tokenSale.enableMasterTransfers({ from: caller })
194 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
195 | return txnReceipt
196 | }
197 |
198 | const lockMasterTransfers = async (tokenSale, caller) => {
199 | let txn = await tokenSale.lockMasterTransfers({from: caller })
200 | let txnReceipt = await waitUntilTransactionsMined(txn.tx)
201 | return txnReceipt
202 | }
203 |
204 | module.exports = {
205 | getWallet,
206 | getToken,
207 | getPresaleToken,
208 | buyTokens,
209 | tokenPrice,
210 | tokenPriceInWei,
211 | pointsMultiplier,
212 | numberOfTokensFor,
213 | getBasePrice,
214 | getBasePriceInWei,
215 | getPrice,
216 | getPriceInWei,
217 | getCap,
218 | getMultisig,
219 | getContributors,
220 | finalize,
221 | enableTransfers,
222 | lockTransfers,
223 | enableMasterTransfers,
224 | lockMasterTransfers
225 | }
226 |
--------------------------------------------------------------------------------
/scripts/transferTokenControl.js:
--------------------------------------------------------------------------------
1 | module.exports = async function (callback) {
2 |
3 | require('babel-register')
4 | require('babel-polyfill')
5 | require('./jsHelpers.js')
6 |
7 | const Web3 = require('web3')
8 | const ProofToken = artifacts.require('./ProofToken.sol')
9 | const TokenSale = artifacts.require('./TokenSale.sol')
10 | const provider = artifacts.options.provider
11 | const web3 = new Web3(provider)
12 | const config = require('../config')
13 |
14 | let proofToken
15 | let tokenSale
16 | let sender
17 |
18 | web3.eth.getAccounts(function(error,result) {
19 | let sender = result[0]
20 | run(sender)
21 | callback()
22 | })
23 |
24 | const run = async function(sender) {
25 | proofToken = await ProofToken.deployed()
26 | tokenSale = await TokenSale.deployed()
27 | let txn = await proofToken.transferControl(tokenSale.address, { from: sender, gas: config.constants.DEFAULT_GAS, gasPrice: config.constants.DEFAULT_HIGH_GAS_PRICE })
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/scripts/transferTokenSaleOwnership.js:
--------------------------------------------------------------------------------
1 | module.exports = async function (callback) {
2 |
3 | require('babel-register')
4 | require('babel-polyfill')
5 | require('./jsHelpers.js')
6 |
7 | const Web3 = require('web3')
8 | const TokenSale = artifacts.require('./TokenSale.sol')
9 | const provider = artifacts.options.provider
10 | const web3 = new Web3(provider)
11 | const config = require('../config')
12 |
13 | let tokenSale
14 | let sender
15 |
16 | let newOwner = '0x2C798A55024Dd46657aD3233e271505D198b36e9'
17 |
18 | web3.eth.getAccounts(function(error,result) {
19 | let sender = result[0]
20 | run(sender)
21 | callback()
22 | })
23 |
24 | const run = async function(sender) {
25 | tokenSale = await TokenSale.deployed()
26 | let txn = await tokenSale.transferOwnership(newOwner, { from: sender, gas: config.constants.DEFAULT_GAS, gasPrice: config.constants.DEFAULT_GAS_PRICE })
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/scripts/utils.js:
--------------------------------------------------------------------------------
1 | const decodeEthereumAddress = (encoded) => {
2 | return '0x' + encoded.slice(26)
3 | }
4 |
5 | module.exports = {
6 | decodeEthereumAddress
7 | }
--------------------------------------------------------------------------------
/scripts/watchEvents.js:
--------------------------------------------------------------------------------
1 | module.exports = async function (callback) {
2 |
3 | require('babel-register')
4 | require('babel-polyfill')
5 | require('./jsHelpers.js')
6 |
7 | const Web3 = require('web3')
8 | const provider = artifacts.options.provider
9 | const web3 = new Web3(provider)
10 |
11 | const ProofToken = artifacts.require('./ProofToken.sol')
12 | const TokenSale = artifacts.require('./TokenSale.sol')
13 |
14 | const proofToken = await ProofToken.deployed()
15 | const proofTokenSale = await TokenSale.deployed()
16 |
17 | console.log(proofToken.address)
18 | console.log(proofTokenSale.address)
19 |
20 | let tokenEvents = proofToken.allEvents()
21 | let tokenSaleEvents = proofTokenSale.allEvents()
22 |
23 | tokenEvents.watch((err,res) => {
24 | console.log("\n****************\n")
25 | console.log(res)
26 | console.log("\n****************\n")
27 | })
28 |
29 | tokenSaleEvents.watch((err,res) => {
30 | console.log("\n****************\n")
31 | console.log(res)
32 | console.log("\n****************\n")
33 | })
34 |
35 | callback()
36 | }
--------------------------------------------------------------------------------
/test/addresses.csv:
--------------------------------------------------------------------------------
1 | Addresses,
2 | 0xcaf15d9cd7cfd573964e3dc88fc6ffea25f89d8f,
3 | 0xf190f0193b694d9d2bb865a66f0c17cbd8280c71,
4 | 0xecd7da67e6563bbddfc2ddff9ba2632c721af181,
5 | 0x31d04a32f22022ec66afe6c2351db768ed32b873,
6 | 0xc7c78f87e2e8d1d55104c8f6fae07966cfc577fd,
7 | 0x72aed3d59cc889b8ab5d943c703f45c4aeaebf86,
8 | 0x6847dedbb505b0b075b98db8f34f1d62f85e0d9d,
9 | 0xac1d10865db58adba0826d94734129ec8a5741d7,
10 | 0xfe8ef260e63a3388bb3f3174cf080f4423414100,
11 | 0x622b2c840d856181661482a2f7d9a5a41e0f992a,
12 | 0xdfa352daf510611ecc1a4ea0d02d6cae8cc3e2e0,
13 | 0x2746dc307f68a8346e9ab34aec63ab358e6dab82,
14 | 0x9c6d12aaa2fb615467c36b4db6b7e3402fb4f45f,
15 | 0x904367561bae5b96b4332c4c5ec338be097b3240,
16 | 0x16ae23df74c294c4fa4c81b278e7c94c25df8c75,
17 | 0x39fc4cdaa0e79efe7687822f1c0bacc87e1deede,
18 | 0x65c6f8dce120363cad39c85e4e5d643cf8126a83,
19 | 0x019dd0bbd3693f838a544df08ed4e2348d82d7a7,
20 | 0x20621e35f40cb15fe63d1af047413a6c5dc304b8,
21 | 0x80f564f022d22730ef980753f97be31b9fe28aae,
22 | 0xc22d2aeecc87e3907c277457e0152deb01c4a55a,
23 | 0x8761e0dd63d14cf566acf4b730f3540f164b6b56,
24 | 0xf7bad6c588967b9a512a423b21a3856744f8d6d8,
25 | 0xe5d93dd474988b60b354339da3a845d9cd35ec5f,
26 | 0x907f20132c1b706026987d592aa6f5bfe83ff314,
27 | 0xb0febed47971f087695d66ea548599f722cd67a5,
28 | 0x763d5862600d0326e14541c0687e79888999b9ab,
29 | 0x5721e592da25b96edd4d44c632cb841ac7ac47bb,
30 | 0x8cbc229cad155b95b4174647ba705d6a414b8cca,
31 | 0x77f6d9261dd8e45c0e8555aa86ab1648da9b95c3,
32 | 0x8c13278a1d8310cd4c6943eb17fad81765992431,
33 | 0xf062ceb02b73515c603707458cb3ffdf484eeb5a,
34 | 0xe0dd6cd8f2053e34ee34bb4c96c16d7e487896db,
35 | 0x62356e055f2165d0c5e812a7445700727a7934da,
36 | 0x9926df844af52a567929c2b32133ccf1c66dd4fd,
37 | 0x0e3374a49caa66c34eda91517dd5de77a9a4bbee,
38 | 0x49fc5195aad930b4df3ec1e50bb14af3586f0793,
39 | 0x553315181e9d643831936b90d63221a335c793ef,
40 | 0xa5959231dda9b429668bf198aa3580d05eb12f2e,
41 | 0xcd5164c8c8a6c4d0c49e6fa5872435c33ab42af5,
42 | 0x37aa7b1343faa68806f453f45b09dd24a1c8f3d4,
43 | 0x3b412c92e78fe2a323a5fc7cd9d31fa0226ffe14,
44 | 0xe92356c05d03fce81063caaafca1493ef6619445,
45 | 0xdd41883adc2e8db3d3e52ae06ce754ab7563a53b,
46 | 0x349b49ac381d097b12f38747447776a0b4d91bfc,
47 | 0x2198eefc694f5d50634a950e10074a11442f41a8,
48 | 0x42d2184dac8580e6224b361a36ca3a917f7ea67b,
49 | 0x01405ab95de872f1745d6b88a155f00f91a7e93e,
50 | 0x7a03a44fe2c6f98debc35800a6899ccf0869be71,
51 | 0x38ea9aeb4a849f9accde0c17ccfaeeb53ba6a393,
52 | 0x009b740f1670af3a6b62d661f182f15a24a010ae,
53 | 0xd6dda35c4216e343b325ccffe0615accae1f82b0,
54 | 0xea9900f8b55efc75c9bca99377e0f026e537544b,
55 | 0x38148ecc2078da7f65e6233dda28efaf4c51e96f,
56 | 0x100dbb75eab5d98ad65ef16483aaa68e68aafbc5,
57 | 0x9e108a4aaa86d2edc1fe4e393c8dfb0f37433559,
58 | 0x67d33cf1c7c699078f86d517a5a1cd1444a1e85c,
59 | 0x712033cf8adc1e60beadb8b52c8a02f02bffe336,
60 | 0xee9baf220c6afe2e846d1788e53ca5a0d3dcb339,
61 | 0xd082c621b2a166b90ab607b11decc4e038045177,
62 | 0x0a8966d44be0272295814e876791431791440256,
63 | 0x9f9f6768fcd665b0ae17f02601a24a60d1eb5dab,
64 | 0x5fe218e03a4a0ccd7f3eeac9a51fd23c0fc369a1,
65 | 0x4bd120e887cc82285aff8408dc208ed32b132bb3,
66 | 0x8d21e3c8993633546e89cb4a24e5c0a5bc4d97e5,
67 | 0x54ce1d1fc211817f280c5e123eb131d7a0b0beb5,
68 | 0xda4cc246162e13f26864cacf19152695d252e671,
69 | 0xac463695dcdf0aa5c16fd74d6be2b831b0512971,
70 | 0x874f59a177348ae3d540d58ac8c5d23a4e77b1e3,
71 | 0x9c79aef1d586452220ff23fa6b7791fcae1e7edb,
72 | 0x6229cf71deccb5d87767e747f5a5c7738db7e40f,
73 | 0x1bf32181e831dbc781eeb850d58f801495c4c93d,
74 | 0xf085548d7bbf66b8731e1a16bd891cad98cb102a,
75 | 0x8c4531b3f4cdfee616a44eaef29b5b5ee60cdf6d,
76 | 0x486291fea9e334ea87efbac640d7d50ffc7bf8c3,
77 | 0xb9c5b4bf86119fb67cc6f3df9632de2b46648143,
78 | 0x901b68e2099f83dcd6e443c86146969ef837ed37,
79 | 0x4866e8a3683d5b7fca9dabfb9d1188a4a152e976,
80 | 0x66ff831f74b212bc5b787c4401a5bc63812aa592,
81 | 0x4089bc81b3e2e986fbd429e03094faf6685200db,
82 | 0x351faf0b10e7d80fbaa8726b41825a71b9922c95,
83 | 0x23cbe4413e92c10c2edf9e7fab336d35be555d86,
84 | 0x0a70de1a644ced8488ec91b4b463826cbf4b5000,
85 | 0xb18b8edb5d4d1fdff2488714747b609941433ea0,
86 | 0xd8c184f93f11c591da6e321c8288c6dba85da99e,
87 | 0x6ba366de900785e24c605e4a8b5261bb23a97fe0,
88 | 0x97dfdcd746dd32b87aaa2d1a0b292f1a38c77aab,
89 | 0x7089a6315f2642ea1f21f81d5fde64f20f80f75e,
90 | 0x8a11d3d03629fbd5cae5f8ef0743bae86868d040,
91 | 0x240d90a0e69ad8f5de91ddcf5fc83cdc30631f04,
92 | 0x6653acb6d74ac95f750a687177c5c3d6a5f14c4d,
93 | 0x081af29ee22c5b902bc6e9c3ce7fa9de77ce8266,
94 | 0xf81753501afc55776320d567c3af6fcdad1204cf,
95 | 0x945ef6fb870fce7614626070af43a95d482fd99a,
96 | 0x7862e990963405616afd1e08cd369433a87adb3a,
97 | 0x8c245d87069a4e463b954778dad9df0039876a9e,
98 | 0x2b8f14e64b3be49c75c816a6e7d9596b259656ad,
99 | 0x0870f0b06a5009d9f6bdad4d3961b4639bb96750,
100 | 0x123e084fc361a878aef966df784f6b3774084028,
101 | 0x971d97f261abb1ecb9967878f45d7be1b374c81d,
102 | 0xedbaaf0005e47f8cd1e70472e93d33543ce1d38e,
103 | 0x3032967bb88c1289c49d9c8a696e8303ee9b7d88,
104 | 0x3ab79bb7d1e17730ab32a28019d890c02c6197f4,
105 | 0x95a4ac9070051437263a019028e0fb7f0c9d12a0,
106 | 0x8fbaf4d323ba4031f8c1c8614317aefb65c626dc,
107 | 0xc60debaa978d0c215c37859f8b59b07910afe807,
108 | 0x76927e2ccab0084bd19cee74f78b63134b9d181e,
109 | 0x927c78cb90407aa4b4e8e12497022e689cc5cb11,
110 | 0xd80b5f92b713a3ee048a752faf889734a4a1db93,
111 | 0xefca48c0672c6ddd1aedc84d7f54ec1b130cf854,
112 | 0xb23b9c52fc16beb6d44e243ba73936a65fc9b709,
113 | 0x7202cba14b504ac90f49aea2b698530fde9481dd,
114 | 0x782b899b1468051b01581548011660b9b1974cab,
115 | 0x8324de24e3c064af46e0dfaf146d392084e38f0c,
116 | 0x4cd24ceb901f903958f2d205d2fc218efa9f3d72,
117 | 0x79785c9729dc6135ff3060d1d8b08780ceb51668,
118 | 0x17bb4076ab59e0ef20ad5a873ab4b5341bf01b78,
119 | 0xb1b33acc4e491ad70f5837250defa92c3816f539,
120 | 0x6dd3a7060d58c8400e13dee3a63fafc8b1f7a7d5,
121 | 0x4e061bae4a29035c55f62a93b339bc57a9073aaf,
122 | 0x10af69bd4435e2c09eaa447eb89a5d3d407f5f47,
123 | 0x6a49dd97e18106c163a9fc6bca3afeb200656f49,
124 | 0xb5d365aca3e16068ab0eb3b39acf6db62c789267,
125 | 0x38a92bb6290284033b5871477fcdc2dc9a744baa,
126 | 0xf6d61560d1b6e70ab61cc58b0daa5b1dff742351,
127 | 0x18addb4b0ea01ad018417d7de4e37b9b6d35c734,
128 | 0xa3b1af9c33c6fdf7852db56263a44b93fb6f687b,
129 | 0xc2116c5a7533d8619c574ce70312f7c2306c00fd,
130 | 0x8f4e9d43583b7d4b8cff5a027220e36401c12b8e,
131 | 0x29809ede7cbe49c6fe1c1dd40513a7bda438473a,
132 | 0x4931b973792aa349108884a26ad0502690f10cdc,
133 | 0x620703fcd6a3ef6773511ef0bc45a558e5647a8c,
134 | 0x2db04d075c2a96e65d8beef44879ed8d07167384,
135 | 0xcaee01dd455e90ac98d84ae847d22261315db192,
136 | 0xdcbbbd8e22d9945f062909923d4524b9630a32ca,
137 | 0xdde972259b65433c769774e504b312de359c031a,
138 | 0x8d3748096d58695246d8735bba837098b8d3fdd7,
139 | 0x932c23938b9bbfaad91ddaf938c622d315eeef34,
140 | 0x739066ed2d1718fd100cec4d9f347382ec6440dc,
141 | 0xb3fa0fa3682bbafaeb95ef288e841609baa5c68b,
142 | 0x59e5fe8a9637702c6d597c5f1c4ebe3fba747371,
143 | 0x66eb0de38cdbbd157d6940b9542a6ca3c98e9080,
144 | 0xc9d4c2fc8c1401eeaa18c048704934f616ed8002,
145 | 0xca14e2076784f7486cf9c1cb4afe194af96bf3fe,
146 | 0x86834a65e12fc6fa4b564b8d0f6b98a4caf88f50,
147 | 0xe2190203932edc3cf358cb497d165a57a0711f77,
148 | 0xf428237037e5c0acf0751f9b42b83d7b4903d305,
149 | 0x89a94b48b21d3b5f959305643d3c71dc88cc7fbc,
150 | 0xe207214e3bc14154f22a59144ccdff6099ca6567,
151 | 0x1eccd61c9fa53a8d2e823a26cd72a7efd7d0e92e,
152 | 0x3833f8dbdbd6bdcb6a883ff209b869148965b364,
153 | 0x9b422e571eb2cb9837efdc4f9087194d65fb070a,
154 | 0x120c322c0b1477a5c2eeb6f9f06d2c98797f485f,
155 | 0xbe6b82da1815de15c1798f2ea58031d793275ff1,
156 | 0x0c38aa3d82aa58ddd9ff8a0ced05f8995950ae4d,
157 | 0x00e96c34d0d80fc23d730ac0702c86ac746f5534,
158 | 0x34b2cf5894ee3e0537e8f45cae265e68d4df4d8c,
159 | 0x69e753860e3a6bb1fead78ab5b5e573e909108c8,
160 | 0xaad68b51814179146d56e824e9bba8f2b5be4f1e,
161 | 0x22c6a17c9d68d0d8cb057435ab087943a62acbbd,
162 | 0x8c3fdeed9f2f79d294300b4b4d182a814107cf6d,
163 | 0x196d791102f53abad22b8d26f5896c4a48146432,
164 | 0x670be3b80f91b0749146a527e7ffbe1397405e9b,
165 | 0x33d87b186a47beb965fdfa207da1ae00d2d7b812,
166 | 0xa106379acb22df279f1ac3c0299742531b3ba6ee,
167 | 0xb2dd65f58594ce19fcfa7daac204587a3287899b,
168 | 0x525a7eb5dbd784feee9a4667f560406f1ea5367a,
169 | 0x26eeb2711ac35bf1c88b6c0bff75a4dd9e02d636,
170 | 0x6ed8cd17ee5453e17eb731a6b2004af53ea1f26a,
171 | 0xf8bad169cb40a0471d2f30b5772bf2ab7b7c0ee8,
172 | 0xbd131d488746eb914fbb4174b783a1b3d77f25e2,
173 | 0x2764281f229fd932b93c5bc9bf3ed2f7ebdd8d9c,
174 | 0x2707bcc067112cd420159b667c47f1dbfc858df2,
175 | 0xb93147f598f8fc20f9cd6276e56b49dfb608eb16,
176 | 0x22b0ac0be4633f57fa4457268ad365c11227e172,
177 | 0xa87d8906eabb8dfb38cc2370a36afaf013d51857,
178 | 0xb904c6901359606d7954bc0dcaaabad3ac33d6c4,
179 | 0x96921dd0a92ed047954d977e4363ec15a0b807d8,
180 | 0x1f4b0a926e0a1b492bb17bfdb8647d658701b08c,
181 | 0x597aa8e340582363f74acc894b51447a2b7d040c,
182 | 0x2f16cc0f50b1e7088177f71ab02985d4daaf7a03,
183 | 0xd4f756dadd2eb06bd14066a882f611636bf16129,
184 | 0xf59fd77afe562aa4e5b66da6e7a67b4651fac538,
185 | 0x1f81da5cc554766d3626dae05bdc6515522bb00f,
186 | 0x8f53518d306cd730652b166005aaaa1f1dd0c137,
187 | 0x18cb0c10e271fa2daca76fb03afe0fc02e83ab74,
188 | 0x9ea60ba8a75f47757f516fb1b8d48d848504a26c,
189 | 0x5ad003a9a02037b196362784f4a53e72198a0a47,
190 | 0xec9e1351c0dcc363b4d027f93ef196b023f0794f,
191 | 0x95dc704ddaa7708f7c8ec220c3f19fdfd81ae708,
192 | 0xf60bddbf39c3e60a50b328230b851a211db134c7,
193 | 0xa55638362ceda5245fa87471ac80189e8d7ad5c4,
194 | 0x82d99d98115565d2a58e99fc53704cee56e3c0de,
195 | 0x71a93ff96b59b96d2caf474b9a79a51f5b043dc3,
196 | 0x43ffdc79fbcedf718a19ad7d7eb2a705696546e4,
197 | 0xfd5a044f5211b1054d6e18b9cb6ece538ec3057f,
198 | 0x8a9354835138d2367923622f27d6c377546175e0,
199 | 0x609723885766759aaf726c241afaa3fb82a3580a,
200 | 0xcc979952371ba7873983b3fadd38649496d206af,
201 | 0xd4bccbde6dc6c922edd96fa1bfa82f03454fbfd8,
202 | 0x7fd44298916ebcb7ffd80bc2b44c918e5333ec3d,
203 | 0xf2787ca2de0b2d20c6cc9bc1ef3519d7eeba47ae,
204 | 0xc285d754df88d0283adbee7027bdb38f3a38adb6,
205 | 0x81c831e3ed24d4b97585c1a371c7aabeba839bb4,
206 | 0xdba4fd71bcd12a9188a365fccc796c65381b49f1,
207 | 0x071b572c7d6b423973078ae08981d944961775f4,
208 | 0x056d01e62c5b2568517d3af63447076e1456998c,
209 | 0x1b3f224bf8fdb4c23fbd6056fe062ffd456b09d6,
210 | 0x91d7833bf076eb16d51f5bff598ad42f4e79bb51,
211 | 0x92a898d46f19719c38126a8a3c27867ae2cee596,
212 | 0xc24b1a1a4cde1c628202a345708653334d30f05f,
213 | 0x31e156678b8f96005f14f91676bef642c28ad06c,
214 | 0x8d12a197cb00d4747a1fe03395095ce2a5cc6819,
215 | 0x74f9d4f1f58686fb8725c29f9ab2cdd2913dd1f0,
216 | 0x2c21e83a76b2dea9fb85885257eb1ac3f82da450,
217 | 0x34bd23da4689788dfa8e6521f979f5eaa3831b3e,
218 | 0xef3c3dfb36ae7c32f509ec1676659ff86ab3f394,
219 | 0x666d77e5b67ddb1f861b3485b70c60b5256a3aa8,
220 | 0xe9ebee76a902b6536c0bddf79ac4c4343e5bdbfb,
221 | 0x8038339ca5c71a11eb321986bf7acd1282da84d5,
222 | 0xad032694466f2b56b11e8258747af91bf72ed791,
223 | 0xf697eeca8130513cc59b1a3ebcc098ba5c10d80c,
224 | 0x4ea5fb82a9ad7cae9bc4357ee0368eb73f9de17d,
225 | 0x00c5a971dafa5e8e2dcff0af9571e2dbe4f4a0bf,
226 | 0x2f2862e9818ca4ada4ae69e700e3a806236d997e,
227 | 0xc7075ed6bf05549ed8e0d6b11f58721040ab4d05,
228 | 0xc9dd260b16b9402e6244f34a8c52dfdcd6eb9113,
229 | 0xce6d2f7b55eb3066c14b4047b2017d7000697e14,
230 | 0x73aa55afb6f0258b2e8b723b7598eb3b3a8312ed,
231 | 0x76bf705e423ccc18f699f275c7bc2d506090acda,
232 | 0x68f521a871ddd406a57121bf7246c7574bc3cb62,
233 | 0x41bacae05437a3fe126933e57002ae3f129aa079,
234 | 0xcc8f79950bfe3d292608321351c4d45d497a7c6d,
235 | 0x63eed78361018f43cb46fa48a6122e004d963a2d,
236 | 0x3a02b24bf0bfc7b9c485eba503fd73e751ca0b00,
237 | 0x4062b2b12b354bf8f9398685a29e1f5e534f95a8,
238 | 0x286f0171bb5c940314c83c9cd9e355106a7de7e7,
239 | 0x33a96b5993f65e26ad4f51b3d3ccea513271b923,
240 | 0xce838139e92080e8e1266092bafb64d1e43dd139,
241 | 0x133f9d96901e3727596660d32dbdcbcf57c03dbb,
242 | 0xfa60838ac163b8b44108b92c8b64c7c15fd5d1bd,
243 | 0x4fc15720ac8dfbdd20aa47c518cf26ee2fc39ef7,
244 | 0x4e89c8b0cefe3b3239a168325baacec8c1cee218,
245 | 0x450f5f260559e4861cd703b61bb9e5e0c622ef29,
246 | 0x4ecec940deabb584b43f21c91b1238bd43b5e7eb,
247 | 0x9e3e93fc983d84e6397e35bc5cd3c33783041f35,
248 | 0xb8c5bb7d01294f5148488786ac9578e97ffb95fd,
249 | 0xcab61b858a344ad4c878c60de62b2019d3e00aed,
250 | 0x7a82fb208303aab2369105ba03c9c0146ac8fd86,
251 | 0x607e4d73800332bf29ff7729a8b519cce7d54202,
252 | 0xcb37a8f731b4db7238d4f4683824ca54decdbce2,
253 | 0x4a789c070535b51ef86628dc995813c6c2eddb32,
254 | 0x70540666f778b7111d62cd6a9ea8a35f44d4076a,
255 | 0xdee028822bc40ac1d6bb042c2378796efdce8bd9,
256 | 0xab697f58c8e9525df5337052cd71d1ba6fff7306,
257 | 0x56532086984e9f6e806cd20c0d241f97b8fe18d9,
258 | 0x4c5aa30f63955ed90e2c47b401dd67e7a409735b,
259 | 0x2beea5ee986b5fd028f4fa64f832020f3ca35aad,
260 | 0x58562bcb3ccaa3b773053eb61d700c7a20884b50,
261 | 0x801f28a3c0813395ed6f2a7216fa16c88917a542,
262 | 0x3e2021221b0bb5e2d1ceda9f024ed9804b055708,
263 | 0x4212fb436bb377cc3c10f5e2f16894daefa68f2f,
264 | 0xa72c38bd35ef32267b6a9315ad3cf36e2624767e,
265 | 0x53dd1454af6da0c6c80230c6f4ba06352b46fd7c,
266 | 0x6aaf4ca8f73f28acf8ae1d8d90465cc9026fd415,
267 | 0xebb62cf8e22c884b1b28c6fa88fbbc17938aa787,
268 | 0x7bacdb8b1aa9390a1ceee85c1e26a9f03671fd43,
269 | 0x0644c1a6d61e0994c73c86febdf64ec8432b1013,
270 | 0x0bbde14072a835903f2f687dd64dd990680e967f,
271 | 0xd07d158d62b1f2c657ceb7331b75de868b83dccf,
272 | 0x60fee5affc433a53e8751fe55fc4bd1794f5ff51,
273 | 0x13148f7a44f78415ba50e8d6a9d7f97ad5a5aff6,
274 | 0x2b5dbb6907816e4ab6182bf58dae543b48ff319a,
275 | 0x7d2330b2906bfdf1c192fc8b750081a2ee6f8328,
276 | 0x57d0c97313bef304f99f338285de6fdce26d0486,
277 | 0xd82ab13c28b70d2a904e03faf15c48df1c970926,
278 | 0x26444302825fbe13d5a5d1c7e7c5759ca67f490d,
279 | 0x32035a7f88db2ae8b66e84fc9333084fa27d88fb,
280 | 0x388e431d70958a5f338a94081d244ec82165ba9b,
281 | 0x7401d01a9bcf8ee5d44b57f255d8a7c14a12d80c,
282 | 0x0fac3479b2eacb02445932e5b65122d6ffab3db8,
283 |
--------------------------------------------------------------------------------
/test/cloneProofToken.js:
--------------------------------------------------------------------------------
1 | require('../scripts/jsHelpers.js')
2 |
3 | const fs = require('fs')
4 | const csv = require('csv-parser')
5 | const json2csv = require('json2csv')
6 | const ethereumAddress = require('ethereum-address')
7 |
8 | const BigNumber = web3.BigNumber
9 | let chai = require('chai')
10 | var chaiAsPromised = require('chai-as-promised')
11 | var chaiStats = require('chai-stats')
12 | var chaiBigNumber = require('chai-bignumber')(BigNumber)
13 | chai.use(chaiAsPromised).use(chaiBigNumber).use(chaiStats).should()
14 |
15 | import moment from 'moment'
16 |
17 | import {
18 | ether
19 | } from '../scripts/testConfig.js'
20 |
21 | import {
22 | getAddress,
23 | getTxnReceiptTopics,
24 | latestTime,
25 | increaseTime
26 | } from '../scripts/helpers.js'
27 |
28 | import {
29 | cloneToken,
30 | getTokenBalance,
31 | getTotalSupply,
32 | transferToken,
33 | baseUnits
34 | } from '../scripts/tokenHelpers.js'
35 |
36 | import {
37 | buyTokens,
38 | enableTransfers
39 | } from '../scripts/tokenSaleHelpers.js'
40 |
41 | import {
42 | transferControl
43 | } from '../scripts/controlHelpers.js'
44 |
45 | import {
46 | decodeEthereumAddress
47 | } from '../scripts/utils.js'
48 |
49 | const assert = chai.assert
50 | const should = chai.should()
51 | const expect = chai.expect
52 |
53 | const ProofToken = artifacts.require('./ProofToken.sol')
54 | const TokenSale = artifacts.require('./TokenSale.sol')
55 | const TokenFactory = artifacts.require('./TokenFactory.sol')
56 |
57 | contract('cloneProofToken', ([fund, buyer, buyer2, wallet]) => {
58 | let tokenSale
59 | let proofToken
60 | let proofTokenFactory
61 | let proofTokenFactoryAddress
62 |
63 | let proofTokenAddress
64 | let tokenSaleAddress
65 | let startTime
66 | let endTime
67 | let contractUploadTime
68 |
69 | let txnReceipt
70 | let topics
71 | let clonedTokenAddress
72 | let clonedToken
73 |
74 | beforeEach(async function() {
75 |
76 | proofTokenFactory = await TokenFactory.new()
77 | proofTokenFactoryAddress = await getAddress(proofTokenFactory)
78 |
79 | proofToken = await ProofToken.new(
80 | proofTokenFactoryAddress,
81 | '0x0',
82 | 0,
83 | 'Proof Token',
84 | 'PRFT'
85 | )
86 |
87 | proofTokenAddress = await getAddress(proofToken)
88 |
89 | contractUploadTime = latestTime()
90 | startTime = contractUploadTime.add(1, 'day').unix()
91 | endTime = contractUploadTime.add(1, 'day').unix()
92 |
93 | tokenSale = await TokenSale.new(
94 | proofTokenAddress,
95 | startTime,
96 | endTime
97 | )
98 |
99 | tokenSaleAddress = await getAddress(tokenSale)
100 |
101 | await transferControl(proofToken, fund, tokenSaleAddress)
102 | await increaseTime(moment.duration(1.01, 'day'))
103 | })
104 |
105 | describe('Cloning: ', function () {
106 | beforeEach(async function() {
107 |
108 | let config = {
109 | name: 'Proof Token',
110 | symbol: 'PRFT2',
111 | block: 0
112 | }
113 |
114 | await buyTokens(tokenSale, buyer, 1 * ether)
115 |
116 | txnReceipt = await cloneToken(proofToken, fund, config)
117 | topics = getTxnReceiptTopics(txnReceipt)
118 | clonedTokenAddress = decodeEthereumAddress(topics[0].parameters[0])
119 | clonedToken = await ProofToken.at(clonedTokenAddress)
120 | })
121 |
122 | it('token should be cloneable', async function () {
123 | let validAddress = ethereumAddress.isAddress(clonedTokenAddress)
124 | validAddress.should.be.true
125 | })
126 |
127 | it('cloned token should return identical balances', async function() {
128 | let balance = await getTokenBalance(proofToken, buyer)
129 | let clonedBalance = await getTokenBalance(clonedToken, buyer)
130 | clonedBalance.should.be.equal(balance)
131 | })
132 |
133 | it('should return identical total supply', async function() {
134 | let totalSupply = await getTotalSupply(proofToken)
135 | let clonedTotalSupply = await getTotalSupply(clonedToken)
136 | clonedTotalSupply.should.be.equal(totalSupply)
137 | })
138 |
139 | it('should be pluggable and buyable via a new tokensale instance', async function() {
140 |
141 | let clonedTokenSale = await TokenSale.new(
142 | clonedTokenAddress,
143 | startTime,
144 | endTime
145 | )
146 |
147 | let clonedTokenSaleAddress = await getAddress(clonedTokenSale)
148 | await transferControl(clonedToken, fund, clonedTokenSaleAddress)
149 |
150 | let initialTokenBalance = await getTokenBalance(clonedToken, buyer2)
151 | await buyTokens(clonedTokenSale, buyer2, 1 * ether)
152 |
153 | let tokenBalance = await getTokenBalance(clonedToken, buyer2)
154 | let balanceIncrease = (tokenBalance - initialTokenBalance)
155 | balanceIncrease = await baseUnits(clonedToken, balanceIncrease)
156 | expect(balanceIncrease).almost.equal(13.3689839572)
157 | })
158 |
159 | it('cloned tokens should be transferable', async function() {
160 |
161 | let clonedTokenSale = await TokenSale.new(
162 | clonedTokenAddress,
163 | startTime,
164 | endTime
165 | )
166 |
167 | let clonedTokenSaleAddress = await getAddress(clonedTokenSale)
168 | await transferControl(clonedToken, fund, clonedTokenSaleAddress)
169 | await enableTransfers(clonedTokenSale, fund)
170 | let buyer1InitialBalance = await getTokenBalance(clonedToken, buyer)
171 | let buyer2InitialBalance = await getTokenBalance(clonedToken, buyer2)
172 |
173 | await transferToken(clonedToken, buyer, buyer2, 100)
174 |
175 | let buyer1Balance = await getTokenBalance(clonedToken, buyer)
176 | let buyer2Balance = await getTokenBalance(clonedToken, buyer2)
177 |
178 | buyer1Balance.should.be.equal(buyer1InitialBalance - 100)
179 | buyer2Balance.should.be.equal(buyer2InitialBalance + 100)
180 | })
181 | })
182 | })
183 |
--------------------------------------------------------------------------------
/test/initialState.js:
--------------------------------------------------------------------------------
1 | const BigNumber = web3.BigNumber
2 | let chai = require('chai')
3 | var chaiAsPromised = require('chai-as-promised')
4 | var chaiStats = require('chai-stats')
5 | var chaiBigNumber = require('chai-bignumber')(BigNumber)
6 | chai.use(chaiAsPromised).use(chaiBigNumber).use(chaiStats).should()
7 |
8 | import { TOKENS_ALLOCATED_TO_PROOF } from '../scripts/testConfig.js'
9 | import { getAddress, latestTime } from '../scripts/helpers.js'
10 | import { baseUnits, mintToken } from '../scripts/tokenHelpers.js'
11 | import { transferOwnership } from '../scripts/ownershipHelpers.js'
12 | import { transferControl } from '../scripts/controlHelpers.js'
13 | import { getPrice } from '../scripts/tokenSaleHelpers.js'
14 |
15 | const assert = chai.assert
16 | const should = chai.should()
17 | const expect = chai.expect
18 |
19 | const ProofPresaleToken = artifacts.require('./ProofPresaleToken.sol')
20 | const ProofToken = artifacts.require('./ProofToken.sol')
21 | const TokenSale = artifacts.require('./TokenSale.sol')
22 |
23 | contract('Crowdsale', (accounts) => {
24 | let fund = accounts[0]
25 | let tokenSale
26 | let tokenSaleAddress
27 | let proofToken
28 | let proofPresaleToken
29 | let proofPresaleTokenAddress
30 | let proofTokenAddress
31 | let sender = accounts[1]
32 | let proofWalletAddress = accounts[9]
33 |
34 | let startTime
35 | let endTime
36 | let contractUploadTime
37 |
38 | let proofMultiSig = '0x99892ac6da1b3851167cb959fe945926bca89f09'
39 |
40 | beforeEach(async function() {
41 |
42 | proofPresaleToken = await ProofPresaleToken.new()
43 | proofPresaleTokenAddress = await getAddress(proofPresaleToken)
44 |
45 | proofToken = await ProofToken.new(
46 | '0x0',
47 | '0x0',
48 | 0,
49 | 'Proof Token Test',
50 | 'PRFT Test'
51 | )
52 |
53 | proofTokenAddress = await getAddress(proofToken)
54 |
55 | contractUploadTime = latestTime()
56 | startTime = contractUploadTime.add(1, 'day').unix()
57 | endTime = contractUploadTime.add(31, 'day').unix()
58 |
59 |
60 | tokenSale = await TokenSale.new(
61 | proofTokenAddress,
62 | startTime,
63 | endTime)
64 |
65 | tokenSaleAddress = await getAddress(tokenSale)
66 | })
67 |
68 | // it('should be ended only after end', async function() {
69 | // let ended = await tokenSale.hasEnded()
70 | // ended.should.equal(false)
71 | // })
72 |
73 | describe('Initial State', function () {
74 |
75 | beforeEach(async function() {
76 | transferControl(proofToken, fund, tokenSaleAddress)
77 | })
78 |
79 | it('should initially set the multisig', async function() {
80 | let multisig = await tokenSale.proofMultiSig.call()
81 | multisig.should.be.equal(proofMultiSig)
82 | })
83 |
84 | it('should initially be linked to the Proof token', async function() {
85 | let token = await tokenSale.proofToken.call()
86 | token.should.be.equal(proofTokenAddress)
87 | })
88 |
89 | it('Token base price should be equal to 0.0748 ether', async function() {
90 | let price = await getPrice(tokenSale)
91 | expect(price).almost.equal(0.85 * 0.088)
92 | })
93 | })
94 | })
95 |
--------------------------------------------------------------------------------
/test/ownable.js:
--------------------------------------------------------------------------------
1 | const BigNumber = web3.BigNumber
2 | let chai = require('chai')
3 | var chaiAsPromised = require('chai-as-promised')
4 | var chaiStats = require('chai-stats')
5 | var chaiBigNumber = require('chai-bignumber')(BigNumber)
6 | chai.use(chaiAsPromised).use(chaiBigNumber).use(chaiStats).should()
7 |
8 | import { getAddress,
9 | expectInvalidOpcode } from '../scripts/helpers.js'
10 |
11 | import { transferOwnership } from '../scripts/ownershipHelpers.js'
12 |
13 | const assert = chai.assert
14 | const should = chai.should()
15 | const expect = chai.expect
16 |
17 | const ProofPresaleToken = artifacts.require('./ProofPresaleToken.sol')
18 | const ProofToken = artifacts.require('./ProofToken.sol')
19 | const TokenSale = artifacts.require('./TokenSale.sol')
20 |
21 | contract('Crowdsale', (accounts) => {
22 | let fund = accounts[0]
23 | let tokenSale
24 | let proofToken
25 | let proofPresaleToken
26 | let proofPresaleTokenAddress
27 | let proofTokenAddress
28 | let receiver = accounts[2]
29 | let hacker1 = accounts[3]
30 | let hacker2 = accounts[4]
31 | let wallet = accounts[5]
32 | let proofWalletAddress = accounts[9]
33 |
34 | let startBlock
35 | let endBlock
36 |
37 | beforeEach(async function() {
38 |
39 | startBlock = web3.eth.blockNumber + 10
40 | endBlock = web3.eth.blockNumber + 20
41 |
42 | proofPresaleToken = await ProofPresaleToken.new()
43 | proofPresaleTokenAddress = await getAddress(proofPresaleToken)
44 |
45 | proofToken = await ProofToken.new(proofPresaleTokenAddress, proofWalletAddress)
46 | proofTokenAddress = await getAddress(proofToken)
47 |
48 | proofToken = await ProofToken.new(
49 | '0x0',
50 | '0x0',
51 | 0,
52 | 'Proof Token',
53 | 18,
54 | 'PRFT',
55 | true)
56 |
57 | tokenSale = await TokenSale.new(
58 | proofTokenAddress,
59 | startBlock,
60 | endBlock)
61 | })
62 |
63 | describe('Ownership', function () {
64 | it('should initially belong to contract caller', async function() {
65 | let owner = await tokenSale.owner.call()
66 | assert.equal(owner, fund)
67 | })
68 |
69 | it('should be transferable to another account', async function() {
70 | let owner = await tokenSale.owner.call()
71 | await transferOwnership(tokenSale, owner, receiver)
72 | let newOwner = await tokenSale.owner.call()
73 | assert.equal(newOwner, receiver)
74 | })
75 |
76 | it('should not be transferable by non-owner', async function() {
77 | let owner = await tokenSale.owner.call()
78 | await expectInvalidOpcode(transferOwnership(tokenSale, hacker1, hacker2))
79 | const newOwner = await tokenSale.owner.call()
80 | assert.equal(owner, newOwner)
81 | })
82 | })
83 | })
84 |
--------------------------------------------------------------------------------
/test/pausable.js:
--------------------------------------------------------------------------------
1 | const BigNumber = web3.BigNumber
2 | let chai = require('chai')
3 | var chaiAsPromised = require('chai-as-promised')
4 | var chaiStats = require('chai-stats')
5 | var chaiBigNumber = require('chai-bignumber')(BigNumber)
6 | chai.use(chaiAsPromised).use(chaiBigNumber).use(chaiStats).should()
7 |
8 | import moment from 'moment'
9 |
10 | import {
11 | ether,
12 | DEFAULT_GAS,
13 | DEFAULT_GAS_PRICE
14 | } from '../scripts/testConfig.js'
15 |
16 | import {
17 | getAddress,
18 | expectInvalidOpcode,
19 | latestTime,
20 | increaseTime
21 | } from '../scripts/helpers.js'
22 |
23 | import {
24 | pause,
25 | unpause
26 | } from '../scripts/pausableHelpers.js'
27 |
28 | import {
29 | getTokenBalance,
30 | baseUnits
31 | } from '../scripts/tokenHelpers.js'
32 |
33 | import {
34 | buyTokens,
35 | enableTransfers,
36 | lockTransers,
37 | enableMasterTransfers,
38 | lockMasterTransfers
39 | } from '../scripts/tokenSaleHelpers.js'
40 |
41 | import {
42 | transferOwnership
43 | } from '../scripts/ownershipHelpers.js'
44 |
45 | import {
46 | transferControl
47 | } from '../scripts/controlHelpers.js'
48 |
49 | const assert = chai.assert
50 | const should = chai.should()
51 | const expect = chai.expect
52 |
53 | const ProofPresaleToken = artifacts.require('./ProofPresaleToken.sol')
54 | const ProofToken = artifacts.require('./ProofToken.sol')
55 | const TokenSale = artifacts.require('./TokenSale.sol')
56 |
57 | contract('Crowdsale', (accounts) => {
58 | let fund = accounts[0]
59 | let tokenSale
60 | let tokenSaleAddress
61 | let proofToken
62 | let proofPresaleToken
63 | let proofPresaleTokenAddress
64 | let proofTokenAddress
65 | let sender = accounts[1]
66 | let hacker1 = accounts[3]
67 | let wallet = accounts[5]
68 | let proofWalletAddress = accounts[9]
69 |
70 | let startTime
71 | let endTime
72 | let contractUploadTime
73 |
74 | beforeEach(async function() {
75 |
76 |
77 | proofPresaleToken = await ProofPresaleToken.new()
78 | proofPresaleTokenAddress = await getAddress(proofPresaleToken)
79 |
80 | proofToken = await ProofToken.new(
81 | '0x0',
82 | '0x0',
83 | 0,
84 | 'Proof Token Test',
85 | 'PRFT Test'
86 | )
87 |
88 | proofTokenAddress = await getAddress(proofToken)
89 |
90 | contractUploadTime = latestTime()
91 | startTime = contractUploadTime.add(1, 'day').unix()
92 | endTime = contractUploadTime.add(31, 'day').unix()
93 |
94 | tokenSale = await TokenSale.new(
95 | proofTokenAddress,
96 | startTime,
97 | endTime
98 | )
99 |
100 | tokenSaleAddress = await getAddress(tokenSale)
101 | })
102 |
103 | describe('Pause', function () {
104 | after(async function() {
105 | let crowdsalePaused = await tokenSale.paused.call()
106 | let owner = await tokenSale.owner.call()
107 | if (crowdsalePaused) {
108 | await unpause(tokenSale, owner)
109 | }
110 | })
111 |
112 | beforeEach(async function() {
113 | await transferControl(proofToken, fund, tokenSaleAddress)
114 | await enableTransfers(tokenSale, fund)
115 | await increaseTime(moment.duration(1.01, 'day'))
116 | })
117 |
118 | it('can be paused and unpaused by the owner', async function() {
119 | let crowdsalePaused = await tokenSale.paused.call()
120 | let owner = await tokenSale.owner.call()
121 |
122 | if (crowdsalePaused) {
123 | await unpause(tokenSale, owner)
124 | crowdsalePaused = await tokenSale.paused.call()
125 | expect(crowdsalePaused).to.be.false
126 | }
127 |
128 | await pause(tokenSale, owner)
129 | crowdsalePaused = await tokenSale.paused.call()
130 | expect(crowdsalePaused).to.be.true
131 |
132 | await unpause(tokenSale, owner)
133 | crowdsalePaused = await tokenSale.paused.call()
134 | expect(crowdsalePaused).to.be.false
135 | })
136 |
137 | it('can not be paused non-owner', async function() {
138 | let crowdsalePaused = await tokenSale.paused.call()
139 | let owner = await tokenSale.owner.call()
140 |
141 | // we initially unpause the contract before we carry out the test
142 | if (crowdsalePaused) {
143 | await unpause(tokenSale, owner)
144 | crowdsalePaused = await tokenSale.paused.call()
145 | expect(crowdsalePaused).to.be.false
146 | }
147 |
148 | await expectInvalidOpcode(pause(tokenSale, hacker1))
149 | crowdsalePaused = await tokenSale.paused.call()
150 | expect(crowdsalePaused).to.be.false
151 | })
152 |
153 | it('can not be unpaused non-owner', async function() {
154 | let crowdsalePaused = await tokenSale.paused.call()
155 | let owner = await tokenSale.owner.call()
156 |
157 | // we initially unpause the contract before we carry out the test
158 | if (!crowdsalePaused) {
159 | await pause(tokenSale, owner)
160 | crowdsalePaused = await tokenSale.paused.call()
161 | expect(crowdsalePaused).to.be.true
162 | }
163 |
164 | await expectInvalidOpcode(pause(tokenSale, hacker1))
165 | crowdsalePaused = await tokenSale.paused.call()
166 | expect(crowdsalePaused).to.be.true
167 | })
168 |
169 | it('buying tokens should not be possible if the contract is paused', async function() {
170 | await pause(tokenSale, fund)
171 | let initialBalance = await getTokenBalance(proofToken, sender)
172 |
173 | let params = { from: sender, gas: DEFAULT_GAS, gasPrice: DEFAULT_GAS_PRICE }
174 | await expectInvalidOpcode(tokenSale.buyTokens(1, params))
175 |
176 | let balance = await getTokenBalance(proofToken, sender)
177 | balance.should.be.equal(initialBalance)
178 | })
179 |
180 | it('buying tokens should be possible if the contract is paused and unpaused', async function() {
181 | let initialBalance = await getTokenBalance(proofToken, sender)
182 |
183 | await buyTokens(tokenSale, sender, 1 * ether)
184 | await pause(tokenSale, fund)
185 | await unpause(tokenSale, fund)
186 | await buyTokens(tokenSale, sender, 1 * ether)
187 |
188 | let balance = await getTokenBalance(proofToken, sender)
189 | let balanceIncrease = await baseUnits(proofToken, balance - initialBalance)
190 | expect(balanceIncrease).to.almost.equal(26.737967914)
191 | })
192 | })
193 | })
194 |
195 |
--------------------------------------------------------------------------------
/test/tokenSale.js:
--------------------------------------------------------------------------------
1 | const BigNumber = web3.BigNumber
2 | let chai = require('chai')
3 | var chaiAsPromised = require('chai-as-promised')
4 | var chaiStats = require('chai-stats')
5 | var chaiBigNumber = require('chai-bignumber')(BigNumber)
6 | chai.use(chaiAsPromised).use(chaiBigNumber).use(chaiStats).should()
7 |
8 | import moment from 'moment'
9 | import { TOKENS_ALLOCATED_TO_PROOF, ether } from '../scripts/testConfig.js'
10 | import { getAddress, advanceToBlock, expectInvalidOpcode, waitUntilTransactionsMined, latestTime, increaseTime } from '../scripts/helpers.js'
11 | import { baseUnits, mintToken, getTokenBalance, getTotalSupply } from '../scripts/tokenHelpers.js'
12 | import { transferControl } from '../scripts/controlHelpers.js'
13 | import { enableTransfers, buyTokens, finalize, getCap, getPrice, getPriceInWei, getBasePrice, getBasePriceInWei } from '../scripts/tokenSaleHelpers.js'
14 | import { pause, unpause } from '../scripts/pausableHelpers'
15 |
16 | const assert = chai.assert
17 | const should = chai.should()
18 | const expect = chai.expect
19 |
20 | const ProofPresaleToken = artifacts.require('./ProofPresaleToken.sol')
21 | const ProofToken = artifacts.require('./ProofToken.sol')
22 | const TokenSale = artifacts.require('./TokenSale.sol')
23 |
24 | contract('Crowdsale', (accounts) => {
25 | let fund = accounts[0]
26 | let tokenSale
27 | let tokenSaleAddress
28 | let proofToken
29 | let proofPresaleToken
30 | let proofPresaleTokenAddress
31 | let proofTokenAddress
32 | let sender = accounts[1]
33 | let receiver = accounts[2]
34 | let hacker = accounts[3]
35 | let wallet = accounts[5]
36 | let proofWalletAddress = accounts[9]
37 |
38 | let startTime
39 | let endTime
40 | let contractUploadTime
41 |
42 | beforeEach(async function() {
43 |
44 |
45 | proofPresaleToken = await ProofPresaleToken.new()
46 | proofPresaleTokenAddress = await getAddress(proofPresaleToken)
47 |
48 | proofToken = await ProofToken.new(
49 | '0x0',
50 | '0x0',
51 | 0,
52 | 'Proof Token Test',
53 | 'PRFT Test'
54 | )
55 |
56 | proofTokenAddress = await getAddress(proofToken)
57 |
58 | contractUploadTime = latestTime()
59 | startTime = contractUploadTime.add(1, 'day').unix()
60 | endTime = contractUploadTime.add(31, 'day').unix()
61 |
62 | tokenSale = await TokenSale.new(
63 | proofTokenAddress,
64 | startTime,
65 | endTime)
66 |
67 | tokenSaleAddress = await getAddress(tokenSale)
68 | })
69 |
70 | describe('Token Information', async function() {
71 | beforeEach(async function() {
72 | await transferControl(proofToken, fund, tokenSaleAddress)
73 | await enableTransfers(tokenSale, fund)
74 | await increaseTime(moment.duration(1.1, 'day'))
75 | })
76 |
77 | it('should return the correct token supply', async function() {
78 | await buyTokens(tokenSale, sender, 1 * ether)
79 |
80 | let supply = await getTotalSupply(proofToken)
81 | let tokenSaleDisplaySupply = await getTotalSupply(tokenSale)
82 | supply.should.be.equal(tokenSaleDisplaySupply)
83 | })
84 |
85 | // the token balance of each token holder can also be displayed via the token sale contract - by routing towards the proof token balanceOf() method
86 | // we verify both balances are equal
87 | it('should return the correct token balance (tokenSale.balanceOf must be equal to proofToken.balanceOf)', async function() {
88 | await buyTokens(tokenSale, sender, 1 * ether)
89 | let senderBalance = await getTokenBalance(proofToken, sender)
90 | let senderDisplayBalance = await getTokenBalance(tokenSale, sender)
91 | senderBalance.should.be.equal(senderDisplayBalance)
92 | })
93 | })
94 |
95 | describe('Initial State', function () {
96 | beforeEach(async function() {
97 | await transferControl(proofToken, fund, tokenSaleAddress)
98 | await increaseTime(moment.duration(1.01, 'day'))
99 | })
100 |
101 | it('should initially set the multisig', async function() {
102 | let tokenSaleWallet = await tokenSale.proofMultiSig.call()
103 | tokenSaleWallet.should.be.equal('0x99892ac6da1b3851167cb959fe945926bca89f09')
104 | })
105 |
106 | it('should initially be linked to the Proof token', async function() {
107 | let tokenSaleToken = await tokenSale.proofToken.call()
108 | tokenSaleToken.should.be.equal(proofTokenAddress)
109 | })
110 |
111 | it('Initial Price should be equal to 0.0748 ether', async function() {
112 | let price = await getPrice(tokenSale)
113 | expect(price).almost.equal(0.85 * 0.088)
114 | })
115 |
116 | it('Base Price should be equal to 0.088 ether', async function() {
117 | let price = await getBasePrice(tokenSale)
118 | price.should.be.equal(0.088)
119 | })
120 |
121 | it('cap should be equal to remaining tokens adjusted to multiplier', async function() {
122 | let cap = await getCap(tokenSale)
123 | cap.should.be.equal(1068644)
124 | })
125 | })
126 |
127 | describe('Finalized state', function () {
128 | beforeEach(async function() {
129 |
130 | contractUploadTime = latestTime()
131 | startTime = contractUploadTime.add(1, 'day').unix()
132 | endTime = contractUploadTime.add(31, 'day').unix()
133 | proofPresaleToken = await ProofPresaleToken.new()
134 | proofPresaleTokenAddress = await getAddress(proofPresaleToken)
135 |
136 | proofToken = await ProofToken.new(
137 | '0x0',
138 | '0x0',
139 | 0,
140 | 'Proof Token Test',
141 | 'PRFT Test'
142 | )
143 |
144 | proofTokenAddress = await getAddress(proofToken)
145 |
146 | tokenSale = await TokenSale.new(
147 | proofTokenAddress,
148 | startTime,
149 | endTime)
150 |
151 | tokenSaleAddress = await getAddress(tokenSale)
152 | transferControl(proofToken, fund, tokenSaleAddress)
153 | })
154 |
155 | it('should initially not be finalized', async function() {
156 | let finalized = await tokenSale.finalized.call()
157 | finalized.should.be.false
158 | })
159 |
160 | it('should not be finalizeable if the token sale is not paused', async function() {
161 | await expectInvalidOpcode(finalize(tokenSale, fund))
162 | let finalized = await tokenSale.finalized.call()
163 | finalized.should.be.false
164 | })
165 |
166 | it('should be finalizeable if the token sale is paused', async function() {
167 | await pause(tokenSale, fund)
168 | await finalize(tokenSale, fund)
169 | let finalized = await tokenSale.finalized.call()
170 | finalized.should.be.true
171 | })
172 |
173 | it('should not be finalizeable if the token sale is paused/unpaused', async function() {
174 | await pause(tokenSale, fund)
175 | await unpause(tokenSale, fund)
176 | await expectInvalidOpcode(finalize(tokenSale, fund))
177 | let finalized = await tokenSale.finalized.call()
178 | finalized.should.be.false
179 | })
180 |
181 | it('should not be finalizeable by non-owner', async function() {
182 | await pause(tokenSale, fund)
183 | await expectInvalidOpcode(finalize(tokenSale, hacker))
184 | let finalized = await tokenSale.finalized.call()
185 | finalized.should.be.false
186 | })
187 |
188 | })
189 | })
190 |
--------------------------------------------------------------------------------
/truffle.js:
--------------------------------------------------------------------------------
1 | var config = require('./config')
2 |
3 | require('babel-register')
4 | require('babel-polyfill')
5 |
6 | const LightWalletProvider = require('@digix/truffle-lightwallet-provider')
7 |
8 | module.exports = {
9 | networks: {
10 | development: {
11 | host: 'localhost',
12 | port: 8545,
13 | network_id: '*',
14 | gas: config.constants.MAX_GAS,
15 | from: '0xdf08f82de32b8d460adbe8d72043e3a7e25a3b39' // testprc main account here
16 | },
17 | ethereum: {
18 | provider: new LightWalletProvider({
19 | keystore: '/Users/davidvanisacker/.sigmate/sigmate-v3-tokensale-mainnet.json',
20 | password: 'popcorn123!',
21 | rpcUrl: config.infura.ethereum
22 | }),
23 | network_id: '1',
24 | gas: config.constants.MAX_GAS,
25 | gasPrice: config.constants.DEFAULT_GAS_PRICE
26 | },
27 | ropsten: {
28 | provider: new LightWalletProvider({
29 | keystore: '/Users/davidvanisacker/.sigmate/sigmate-v3-tokensale-ropsten.json',
30 | password: 'popcorn123!',
31 | rpcUrl: config.infura.ropsten
32 | }),
33 | network_id: '3'
34 | },
35 | rinkeby: {
36 | provider: new LightWalletProvider({
37 | keystore: '/Users/davidvanisacker/.sigmate/sigmate-v3-tokensale-rinkeby.json',
38 | password: 'popcorn123!',
39 | rpcUrl: config.infura.rinkeby
40 | }),
41 | network_id: '4'
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const CopyWebpackPlugin = require('copy-webpack-plugin');
3 |
4 | module.exports = {
5 | entry: './app/javascripts/app.js',
6 | output: {
7 | path: path.resolve(__dirname, 'build'),
8 | filename: 'app.js'
9 | },
10 | plugins: [
11 | // Copy our app's index.html to the build folder.
12 | new CopyWebpackPlugin([
13 | { from: './app/index.html', to: "index.html" }
14 | ])
15 | ],
16 | module: {
17 | rules: [
18 | {
19 | test: /\.css$/,
20 | use: [ 'style-loader', 'css-loader' ]
21 | }
22 | ],
23 | loaders: [
24 | { test: /\.json$/, use: 'json-loader' },
25 | {
26 | test: /\.js$/,
27 | exclude: /(node_modules|bower_components)/,
28 | loader: 'babel-loader',
29 | query: {
30 | presets: ['es2015'],
31 | plugins: ['transform-runtime']
32 | }
33 | }
34 | ]
35 | }
36 | }
37 |
--------------------------------------------------------------------------------