From 1fc48c375d05a9b91ddc2f8e78774dce201a35b1 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Fri, 27 Oct 2017 23:01:07 -0700 Subject: [PATCH 01/35] [new] basic functions --- .gitignore | 1 + contracts/Crowdsale.sol | 62 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..723ef36f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index 576ec7e2..b25a9369 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -10,5 +10,65 @@ import './Token.sol'; */ contract Crowdsale { - // YOUR CODE HERE + address public creator; + uint public totalRaised; + uint public currentBalence; + uint private startingTime; + uint private endingTime; + uint public exchangeRate; + Token private token; + Queue public queue; + + modifier isCreator() { + require(msg.sender == creator); + _; + } + + modifier saleHasEnded() { + require(now > startingTime); + _; + } + + modifier saleHasNotEnded() { + require(now <= startingTime); + _; + } + + function Crowdsale(uint256 _exhangeRate, uint256 totalSupply, uint timeCap) { + startingTime = now; + endingTime = startingTime + timeCap; + creator = msg.sender; + token = new Token(totalSupply); + exchangeRate = _exhangeRate; + queue = new Queue(); + } + + function mint(uint256 amount) isCreator() { + token.mint(amount); + } + + function burn(uint256 amount) isCreator() returns (bool) { + return token.burn(amount); + } + + function deliver() payable saleHasNotEnded() returns (bool) { + + } + + + function refund(uint256 amount) saleHasNotEnded() returns (bool) { + bool good = token.refund(msg.sender, amount); + if (good) { + good = msg.sender.send(amount); + } + return good; + // RefundCompleted(msg.sender, success); // event + } + + function withdrawFunds() saleHasEnded() isCreator() returns (bool) { + return creator.send(currentBalence); + } + + function () { throw; } + } From c7239a2351485cfc1ef10072ab085811a3c457ea Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Fri, 27 Oct 2017 23:54:31 -0700 Subject: [PATCH 02/35] finished --- contracts/Crowdsale.sol | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index b25a9369..0f67e032 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -19,18 +19,22 @@ contract Crowdsale { Token private token; Queue public queue; + event TokenDelivered(address receiver, bool status); + event EtherRefunded(address receiver, bool status); + + modifier isCreator() { require(msg.sender == creator); _; } modifier saleHasEnded() { - require(now > startingTime); + require(now > endingTime); _; } modifier saleHasNotEnded() { - require(now <= startingTime); + require(startingTime < now && now < endingTime); _; } @@ -52,7 +56,34 @@ contract Crowdsale { } function deliver() payable saleHasNotEnded() returns (bool) { - + uint tokensAmount = msg.value * exchangeRate; + + if (tokensAmount > (token.totalSupply() - totalRaised)) { + revert(); + return false; + } + + queue.enqueue(msg.sender); + while (queue.checkPlace() > 1) { // until first in line + continue; + } + require((queue.checkPlace() == 1); + + queue.checkTime(); + if (queue.checkPlace() == 0) { // times up + revert(); + TokenDelivered(msg.sender, false); + return false; + } + + while (queue.qsize() < 1) { // until at least 2 nodes in the queue + continue; + } + queue.dequeue(); + bool success = token.transfer(msg.sender, tokensAmount); + TokenDelivered(msg.sender, success); + return success; + } @@ -61,14 +92,14 @@ contract Crowdsale { if (good) { good = msg.sender.send(amount); } + EtherRefunded(msg.sender, good); // event return good; - // RefundCompleted(msg.sender, success); // event } function withdrawFunds() saleHasEnded() isCreator() returns (bool) { return creator.send(currentBalence); } - function () { throw; } + function () { revert(); } } From b636564034d4eb51e3d0fb68f4f754d401298856 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sat, 28 Oct 2017 19:25:15 -0700 Subject: [PATCH 03/35] add requirement for Token --- contracts/Token.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/contracts/Token.sol b/contracts/Token.sol index 7c23c4cf..d71591b9 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -10,4 +10,12 @@ import './interfaces/ERC20Interface.sol'; contract Token is ERC20Interface { // YOUR CODE HERE + + // we need functions from token including following: + // - token.mint(amount); + // - token.burn(amount); + // - token.totalSupply() + // - token.transfer(msg.sender, tokensAmount); + // - token.refund(msg.sender, amount); + // ---> these 5 functions } From c045dd139a0179c67a660c719151b9c55c3d9b87 Mon Sep 17 00:00:00 2001 From: Nitesh Anandan Date: Sat, 28 Oct 2017 19:30:57 -0700 Subject: [PATCH 04/35] queue implemented but not tested --- contracts/Queue.sol | 58 ++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/contracts/Queue.sol b/contracts/Queue.sol index fe0a4275..31eb4f7e 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -8,52 +8,76 @@ pragma solidity ^0.4.15; */ contract Queue { - /* State variables */ + + uint8 size = 5; - // YOUR CODE HERE + uint8 curSize; + uint timeLimit; + participant[] participantsList; - /* Add events */ - // YOUR CODE HERE + struct participant{ + address a; + uint timeLimit; + } - /* Add constructor */ - // YOUR CODE HERE + function Queue(uint _timeLimit) { + timeLimit = _timeLimit; + } /* Returns the number of people waiting in line */ function qsize() constant returns(uint8) { - // YOUR CODE HERE + return curSize; } /* Returns whether the queue is empty or not */ function empty() constant returns(bool) { - // YOUR CODE HERE + return curSize == 0; } - + /* Returns the address of the person in the front of the queue */ function getFirst() constant returns(address) { - // YOUR CODE HERE + if(curSize == 0){ + return address(0); + } + return participantsList[0].a; } - + /* Allows `msg.sender` to check their position in the queue */ function checkPlace() constant returns(uint8) { - // YOUR CODE HERE + for(uint8 i = 0; i < curSize; i++){ + if(participantsList[i].a == msg.sender){ + return i; + } + } + revert(); } - + /* Allows anyone to expel the first person in line if their time * limit is up */ function checkTime() { - // YOUR CODE HERE + if(participantsList[0].timeLimit < now){ + dequeue(); + } } - + /* Removes the first person in line; either when their time is up or when * they are done with their purchase */ function dequeue() { - // YOUR CODE HERE + delete participantsList[0]; + curSize = curSize - 1; + if(curSize> 0){ + participantsList[0].timeLimit = now + timeLimit; + } } /* Places `addr` in the first empty position in the queue */ function enqueue(address addr) { - // YOUR CODE HERE + if(curSize >= size - 1){ + return; + } + participantsList.push(participant( addr, now + timeLimit)); + curSize = curSize + 1; } } From ce63b5abae579ee72b755811245bd1a24ddff476 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sat, 28 Oct 2017 22:38:16 -0700 Subject: [PATCH 05/35] Update Queue.sol --- contracts/Queue.sol | 58 +++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 31eb4f7e..4337db1e 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -9,54 +9,62 @@ pragma solidity ^0.4.15; contract Queue { - uint8 size = 5; - uint8 curSize; uint timeLimit; - participant[] participantsList; + uint8 currentSize; + Participant[] participantsList; - struct participant{ + struct Participant { address a; - uint timeLimit; + uint t; + uint tokensAmount; } - function Queue(uint _timeLimit) { - timeLimit = _timeLimit; + function Queue() { + // initinital constructor + currentSize = 0; + timeLimit = 10; } /* Returns the number of people waiting in line */ function qsize() constant returns(uint8) { - return curSize; + return currentSize; } /* Returns whether the queue is empty or not */ function empty() constant returns(bool) { - return curSize == 0; + return (currentSize == 0); } /* Returns the address of the person in the front of the queue */ function getFirst() constant returns(address) { - if(curSize == 0){ - return address(0); + if(currentSize > 0){ + return participantsList[0].a; } - return participantsList[0].a; + return address(0); } - /* Allows `msg.sender` to check their position in the queue */ + /* Allows `msg.sender` to check their position in the queue. + * Returns the 1-indexed position of the sender in the line. + * If person is not in line, returns 0. + */ function checkPlace() constant returns(uint8) { - for(uint8 i = 0; i < curSize; i++){ - if(participantsList[i].a == msg.sender){ + for(uint8 i = 0; i < currentSize; i++) { + if(participantsList[i].a == msg.sender) { return i; } } - revert(); + return 0; } /* Allows anyone to expel the first person in line if their time * limit is up */ function checkTime() { - if(participantsList[0].timeLimit < now){ + if( + currentSize > 0 && + participantsList[0].t + timeLimit < now) + { dequeue(); } } @@ -65,19 +73,17 @@ contract Queue { * they are done with their purchase */ function dequeue() { - delete participantsList[0]; - curSize = curSize - 1; - if(curSize> 0){ - participantsList[0].timeLimit = now + timeLimit; + if (currentSize > 0) { + delete participantsList[0]; + currentSize = currentSize - 1; } } /* Places `addr` in the first empty position in the queue */ - function enqueue(address addr) { - if(curSize >= size - 1){ - return; + function enqueue(address addr, uint amount) { + if (currentSize < size) { + participantsList.push(Participant(addr, now, amount)); + currentSize += 1; } - participantsList.push(participant( addr, now + timeLimit)); - curSize = curSize + 1; } } From 197e1e9ef58e6a72f58dc971f6c0415421bf2b8c Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sat, 28 Oct 2017 22:41:40 -0700 Subject: [PATCH 06/35] Update Queue.sol --- contracts/Queue.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 4337db1e..6f682382 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -16,7 +16,7 @@ contract Queue { struct Participant { address a; - uint t; + uint timteStamp; uint tokensAmount; } @@ -63,7 +63,7 @@ contract Queue { function checkTime() { if( currentSize > 0 && - participantsList[0].t + timeLimit < now) + participantsList[0].timteStamp + timeLimit < now) { dequeue(); } From e8492f72b1947f759b550a233ac231bbf04e511f Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sat, 28 Oct 2017 22:54:45 -0700 Subject: [PATCH 07/35] drop tokensAmount in participant struct --- contracts/Queue.sol | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 6f682382..a7e964e3 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -16,8 +16,7 @@ contract Queue { struct Participant { address a; - uint timteStamp; - uint tokensAmount; + uint timeStamp; } function Queue() { @@ -38,7 +37,7 @@ contract Queue { /* Returns the address of the person in the front of the queue */ function getFirst() constant returns(address) { - if(currentSize > 0){ + if (currentSize > 0){ return participantsList[0].a; } return address(0); @@ -49,7 +48,7 @@ contract Queue { * If person is not in line, returns 0. */ function checkPlace() constant returns(uint8) { - for(uint8 i = 0; i < currentSize; i++) { + for (uint8 i = 0; i < currentSize; i++) { if(participantsList[i].a == msg.sender) { return i; } @@ -61,9 +60,9 @@ contract Queue { * limit is up */ function checkTime() { - if( + if ( currentSize > 0 && - participantsList[0].timteStamp + timeLimit < now) + participantsList[0].timeStamp + timeLimit < now) { dequeue(); } @@ -82,7 +81,7 @@ contract Queue { /* Places `addr` in the first empty position in the queue */ function enqueue(address addr, uint amount) { if (currentSize < size) { - participantsList.push(Participant(addr, now, amount)); + participantsList.push(Participant(addr, now)); currentSize += 1; } } From 8eb669a47f7128f259e5c4d9256235876a2fe640 Mon Sep 17 00:00:00 2001 From: Jesse Paterson Date: Sun, 29 Oct 2017 00:00:11 -0700 Subject: [PATCH 08/35] token should be done --- contracts/Crowdsale.sol | 6 +- contracts/Token.sol | 95 +++++++++++++++++++++++++ contracts/interfaces/ERC20Interface.sol | 2 +- 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index 0f67e032..91bd647d 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -36,7 +36,7 @@ contract Crowdsale { modifier saleHasNotEnded() { require(startingTime < now && now < endingTime); _; - } + } function Crowdsale(uint256 _exhangeRate, uint256 totalSupply, uint timeCap) { startingTime = now; @@ -85,12 +85,12 @@ contract Crowdsale { return success; } - + function refund(uint256 amount) saleHasNotEnded() returns (bool) { bool good = token.refund(msg.sender, amount); if (good) { - good = msg.sender.send(amount); + good = msg.sender.send(amount*exchangeRate); } EtherRefunded(msg.sender, good); // event return good; diff --git a/contracts/Token.sol b/contracts/Token.sol index d71591b9..701d8ca2 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -18,4 +18,99 @@ contract Token is ERC20Interface { // - token.transfer(msg.sender, tokensAmount); // - token.refund(msg.sender, amount); // ---> these 5 functions + + // Balances for each account + mapping(address => uint256) private balances; + uint256 private totalSupply; + + // Owner of account approves the transfer of an amount to another account + mapping(address => mapping (address => uint256)) allowed; + + function mint(uint256 amount) public{ + totalSupply+=amount; + } + + function burn(uint256 amount) public{ + totalSupply-=amount; + Burn(amount); + } + + function totalSupply() public returns (uint256 total){ + return totalSupply; + } + + /// @notice send `_value` token to `_to` from `msg.sender` + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transfer(address _to, uint256 _value) public{ + if (balances[msg.sender] >= _value && _value > 0 && balances[_to] + _value > balances[_to]) { + balances[msg.sender] -= _value; + balances[_to] += _value; + Transfer(msg.sender, _to, _value); + return true; + } else { + return false; + } + } + + /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` + /// @param _from The address of the sender + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){ + if (balances[_from] >= _value && _value > 0 && balances[_to] + _value > balances[_to]) { + if(msg.sender==_from){ + balances[_from] -= _value; + balances[_to] += _value; + Transfer(_from, _to, _value); + return true; + } else if (allowance(_from, msg.sender)<=value){ + allowed[_from][msg.sender]-=value; + balances[_from] -= _value; + balances[_to] += _value; + Transfer(_from, _to, _value); + return true; + } + } else { + return false; + } + } + + function refund(address _from, uint256 _value) public returns (bool success){ + if (balances[msg.sender] >= _value && _value > 0) { + balances[msg.sender] -= _value; + return true; + } else { + return false; + } + } + + /// @param _owner The address from which the balance will be retrieved + /// @return The balance + function balanceOf(address _owner) public constant returns (uint256 balance){ + return balances[_owner]; + } + + /// @notice `msg.sender` approves `_spender` to spend `_value` tokens + /// @param _spender The address of the account able to transfer the tokens + /// @param _value The amount of tokens to be approved for transfer + /// @return Whether the approval was successful or not + function approve(address _spender, uint256 _value) public returns (bool success){ + allowed[msg.sender][_spender]+=_value; + Approval(msg.sender, _spender, _value); + return true; + } + + /// @param _owner The address of the account owning tokens + /// @param _spender The address of the account able to transfer the tokens + /// @return Amount of remaining tokens allowed to spent + function allowance(address _owner, address _spender) public constant returns (uint256 remaining){ + return allowed[_owner][_spender]; + } + + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); + event Burn(uint256 _value); } diff --git a/contracts/interfaces/ERC20Interface.sol b/contracts/interfaces/ERC20Interface.sol index b1c74cde..d8e5a91a 100644 --- a/contracts/interfaces/ERC20Interface.sol +++ b/contracts/interfaces/ERC20Interface.sol @@ -7,7 +7,7 @@ pragma solidity ^0.4.15; */ contract ERC20Interface { /* This is a slight change to the ERC20 base standard. - + function totalSupply() constant returns (uint256 supply); is replaced with: uint256 public totalSupply; From c32a02eeefe65f68ce7effcbe9326e4dadca70ee Mon Sep 17 00:00:00 2001 From: Jesse Paterson Date: Sun, 29 Oct 2017 00:02:30 -0700 Subject: [PATCH 09/35] an underbar --- contracts/Token.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Token.sol b/contracts/Token.sol index 701d8ca2..5455faa3 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -66,7 +66,7 @@ contract Token is ERC20Interface { balances[_to] += _value; Transfer(_from, _to, _value); return true; - } else if (allowance(_from, msg.sender)<=value){ + } else if (allowance(_from, msg.sender)<=_value){ allowed[_from][msg.sender]-=value; balances[_from] -= _value; balances[_to] += _value; From 58cd456534ed735dde11fe1a586ef75ee69fb9f0 Mon Sep 17 00:00:00 2001 From: Nitesh Anandan Date: Sun, 29 Oct 2017 03:31:52 -0700 Subject: [PATCH 10/35] Added tests for Queue.sol --- contracts/Queue.sol | 3 +- migrations/2_deploy_greeter.js | 12 +++---- test/TestQueue.js | 57 ++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 test/TestQueue.js diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 31eb4f7e..2fec23d3 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -74,9 +74,10 @@ contract Queue { /* Places `addr` in the first empty position in the queue */ function enqueue(address addr) { - if(curSize >= size - 1){ + if(curSize >= size){ return; } + participantsList.push(participant( addr, now + timeLimit)); curSize = curSize + 1; } diff --git a/migrations/2_deploy_greeter.js b/migrations/2_deploy_greeter.js index 09ff1d43..9d7b6999 100755 --- a/migrations/2_deploy_greeter.js +++ b/migrations/2_deploy_greeter.js @@ -1,9 +1,9 @@ -var BadAuction = artifacts.require("./BadAuction.sol"); -var GoodAuction = artifacts.require("./GoodAuction.sol"); -var Poisoned = artifacts.require("./Poisoned.sol"); +var Queue = artifacts.require("./Queue.sol"); +var Crowdsale = artifacts.require("./Token.sol"); +var Token = artifacts.require("./Crowdsale.sol"); module.exports = function(deployer) { - deployer.deploy(BadAuction); - deployer.deploy(GoodAuction); - deployer.deploy(Poisoned); + deployer.deploy(Queue); + deployer.deploy(Crowdsale); + deployer.deploy(Token); }; diff --git a/test/TestQueue.js b/test/TestQueue.js new file mode 100644 index 00000000..a05c5f84 --- /dev/null +++ b/test/TestQueue.js @@ -0,0 +1,57 @@ + +const Queue = artifacts.require("./Queue.sol"); + +contract('TestQueue', function(accounts){ + let queue; + beforeEach(async function() { + let q = await Queue.new(5); + queue = q; + }); + + describe('Test queue operations', function(){ + it("Testing enqueue operations, qsize should increment upon enqueue", async function() { + await queue.enqueue(0); + let size = await queue.qsize.call(); + assert.equal( size, 1, "qsize should equal 1"); + }), + it("Testing enqueue operations, adding more than 5 participants should fail.", async function() { + for(let i = 0; i < 10; i++){ + await queue.enqueue(i); + } + let size = await queue.qsize.call(); + assert.equal(size, 5, "qsize should never be more than 5"); + }), + it("Testing dequeue after enqueue", async function() { + await queue.enqueue(1); + await queue.enqueue(2); + await queue.enqueue(3); + await queue.dequeue(); + let size = await queue.qsize.call(); + assert.equal(size, 2, "Adding 3 participants and dequeueing, should result in 2 participants."); + }), + it("getFirst should fetch address correspponding to the first participant in queue", async function() { + await queue.enqueue(accounts[0]); + await queue.enqueue(accounts[1]); + let first = await queue.getFirst.call(); + assert.equal(first, accounts[0], "First person in queue"); + }), + it("checkPlace should return position of participant", async function() { + await queue.enqueue(accounts[0]); + await queue.enqueue(accounts[1]); + await queue.enqueue(accounts[2]); + let position = await queue.checkPlace.call({from: accounts[1]}); + assert.equal(position, 1, "accounts[1] is at position 1"); + }) + }); + describe("Test participant time limits", function(){ + it("checkTime for first participant in queue should work", async function(){ + await queue.enqueue(accounts[0]); + + setTimeout( async function(){ + await queue.checkTime(); + let size = await queue.qsize.call(); + assert.equal(size, 0, "checktime after waiting 3 seconds should remove participant from queue"); + }, 3000); + }) + }) +}); From 6e61bb9d59efe874a728e9cbdc44cfddb5fb7c28 Mon Sep 17 00:00:00 2001 From: Nitesh Anandan Date: Sun, 29 Oct 2017 04:08:03 -0700 Subject: [PATCH 11/35] Fixed constructor --- contracts/Queue.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 33c70d63..c54380ac 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -19,10 +19,9 @@ contract Queue { uint timeStamp; } - function Queue() { + function Queue(uint _timeLimit) { // initinital constructor - currentSize = 0; - timeLimit = 10; + timeLimit = _timeLimit; } /* Returns the number of people waiting in line */ From 304b8f0174cb3b5a08de312d7caa8dc511870f3b Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 13:29:54 -0700 Subject: [PATCH 12/35] update styles --- contracts/Crowdsale.sol | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index 0f67e032..0a98a9cb 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -22,7 +22,6 @@ contract Crowdsale { event TokenDelivered(address receiver, bool status); event EtherRefunded(address receiver, bool status); - modifier isCreator() { require(msg.sender == creator); _; @@ -38,12 +37,16 @@ contract Crowdsale { _; } - function Crowdsale(uint256 _exhangeRate, uint256 totalSupply, uint timeCap) { + function Crowdsale( + uint256 _exhangeRate, + uint256 totalSupply, + uint _timeInMinutesForFundraising) + { startingTime = now; - endingTime = startingTime + timeCap; + endingTime = startingTime + (_timeInMinutesForFundraising * 1 minutes); creator = msg.sender; - token = new Token(totalSupply); exchangeRate = _exhangeRate; + token = new Token(totalSupply); queue = new Queue(); } @@ -63,11 +66,12 @@ contract Crowdsale { return false; } - queue.enqueue(msg.sender); + queue.enqueue(msg.sender, tokensAmount); + while (queue.checkPlace() > 1) { // until first in line continue; } - require((queue.checkPlace() == 1); + require( queue.checkPlace() == 1 ); queue.checkTime(); if (queue.checkPlace() == 0) { // times up @@ -81,6 +85,9 @@ contract Crowdsale { } queue.dequeue(); bool success = token.transfer(msg.sender, tokensAmount); + if (success) { + currentBalence += msg.value; + } TokenDelivered(msg.sender, success); return success; From 7e7d33ded05a213b985927cf7a18bf9899688b20 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 13:32:37 -0700 Subject: [PATCH 13/35] update limite --- contracts/Crowdsale.sol | 2 +- contracts/Queue.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index a0b0d7ee..aa9dab6c 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -47,7 +47,7 @@ contract Crowdsale { creator = msg.sender; exchangeRate = _exhangeRate; token = new Token(totalSupply); - queue = new Queue(); + queue = new Queue(100); } function mint(uint256 amount) isCreator() { diff --git a/contracts/Queue.sol b/contracts/Queue.sol index c54380ac..072d270e 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -82,7 +82,7 @@ contract Queue { if(currentSize >= size){ return; } - ParticipantsList.push(Participant( addr, now + timeLimit)); + ParticipantsList.push(Participant( addr, now )); currentSize = currentSize + 1; } } From c2e6598d1eaea0c5bf5966b2e6d5bbfbbde45b86 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 13:40:10 -0700 Subject: [PATCH 14/35] minor updates --- contracts/Crowdsale.sol | 6 +++--- contracts/Queue.sol | 1 + contracts/Token.sol | 14 +++++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index aa9dab6c..ec7ef3de 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -39,14 +39,14 @@ contract Crowdsale { function Crowdsale( uint256 _exhangeRate, - uint256 totalSupply, + uint256 _totalSupply, uint _timeInMinutesForFundraising) { startingTime = now; endingTime = startingTime + (_timeInMinutesForFundraising * 1 minutes); creator = msg.sender; exchangeRate = _exhangeRate; - token = new Token(totalSupply); + token = new Token(_totalSupply); queue = new Queue(100); } @@ -66,7 +66,7 @@ contract Crowdsale { return false; } - queue.enqueue(msg.sender, tokensAmount); + queue.enqueue(msg.sender); while (queue.checkPlace() > 1) { // until first in line continue; diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 072d270e..229d1740 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -80,6 +80,7 @@ contract Queue { /* Places `addr` in the first empty position in the queue */ function enqueue(address addr) { if(currentSize >= size){ + revert(); return; } ParticipantsList.push(Participant( addr, now )); diff --git a/contracts/Token.sol b/contracts/Token.sol index 5455faa3..62e54477 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -21,22 +21,26 @@ contract Token is ERC20Interface { // Balances for each account mapping(address => uint256) private balances; - uint256 private totalSupply; + uint256 private totalSupplyAmount; // Owner of account approves the transfer of an amount to another account mapping(address => mapping (address => uint256)) allowed; + function Token(uint _totalSupplyAmount) { + totalSupplyAmount = _totalSupplyAmount + } + function mint(uint256 amount) public{ - totalSupply+=amount; + totalSupplyAmount += amount; } function burn(uint256 amount) public{ - totalSupply-=amount; + totalSupplyAmount -= amount; Burn(amount); } function totalSupply() public returns (uint256 total){ - return totalSupply; + return totalSupplyAmount; } /// @notice send `_value` token to `_to` from `msg.sender` @@ -67,7 +71,7 @@ contract Token is ERC20Interface { Transfer(_from, _to, _value); return true; } else if (allowance(_from, msg.sender)<=_value){ - allowed[_from][msg.sender]-=value; + allowed[_from][msg.sender] -= _value; balances[_from] -= _value; balances[_to] += _value; Transfer(_from, _to, _value); From cbb8abee4c47609c41657f55e9a278e5ffe40595 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 13:47:26 -0700 Subject: [PATCH 15/35] fixed mutiple bugs --- contracts/Crowdsale.sol | 4 ++-- contracts/Token.sol | 31 +++++++++++++------------------ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index ec7ef3de..304c7e76 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -54,8 +54,8 @@ contract Crowdsale { token.mint(amount); } - function burn(uint256 amount) isCreator() returns (bool) { - return token.burn(amount); + function burn(uint256 amount) isCreator() { + token.burn(amount); } function deliver() payable saleHasNotEnded() returns (bool) { diff --git a/contracts/Token.sol b/contracts/Token.sol index 62e54477..8d895eeb 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -18,44 +18,41 @@ contract Token is ERC20Interface { // - token.transfer(msg.sender, tokensAmount); // - token.refund(msg.sender, amount); // ---> these 5 functions + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); + event Burn(uint256 _value); // Balances for each account mapping(address => uint256) private balances; - uint256 private totalSupplyAmount; // Owner of account approves the transfer of an amount to another account mapping(address => mapping (address => uint256)) allowed; function Token(uint _totalSupplyAmount) { - totalSupplyAmount = _totalSupplyAmount + totalSupply = _totalSupplyAmount; } - function mint(uint256 amount) public{ - totalSupplyAmount += amount; + function mint(uint256 amount) { + totalSupply += amount; } - function burn(uint256 amount) public{ - totalSupplyAmount -= amount; + function burn(uint256 amount) { + totalSupply -= amount; Burn(amount); } - function totalSupply() public returns (uint256 total){ - return totalSupplyAmount; - } - /// @notice send `_value` token to `_to` from `msg.sender` /// @param _to The address of the recipient /// @param _value The amount of token to be transferred /// @return Whether the transfer was successful or not - function transfer(address _to, uint256 _value) public{ + function transfer(address _to, uint256 _value) public returns (bool) { if (balances[msg.sender] >= _value && _value > 0 && balances[_to] + _value > balances[_to]) { balances[msg.sender] -= _value; balances[_to] += _value; Transfer(msg.sender, _to, _value); return true; - } else { - return false; } + return false; } /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` @@ -83,8 +80,8 @@ contract Token is ERC20Interface { } function refund(address _from, uint256 _value) public returns (bool success){ - if (balances[msg.sender] >= _value && _value > 0) { - balances[msg.sender] -= _value; + if (balances[_from] >= _value && _value > 0) { + balances[_from] -= _value; return true; } else { return false; @@ -114,7 +111,5 @@ contract Token is ERC20Interface { return allowed[_owner][_spender]; } - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); - event Burn(uint256 _value); + } From 0f13b2c0367e945c77e700cf78d1ae80962e7575 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 13:52:23 -0700 Subject: [PATCH 16/35] fix the missing currentSize initialization --- contracts/Queue.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 229d1740..56b72a34 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -21,6 +21,7 @@ contract Queue { function Queue(uint _timeLimit) { // initinital constructor + currentSize = 0; timeLimit = _timeLimit; } @@ -73,7 +74,7 @@ contract Queue { function dequeue() { if (currentSize > 0) { delete ParticipantsList[0]; - currentSize = currentSize - 1; + currentSize -= 1; } } @@ -84,6 +85,6 @@ contract Queue { return; } ParticipantsList.push(Participant( addr, now )); - currentSize = currentSize + 1; + currentSize += 1; } } From 8b657968b6c53951bf5c83488a3ef6b9de14a4f4 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 17:18:15 -0700 Subject: [PATCH 17/35] fix styling --- contracts/Token.sol | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/contracts/Token.sol b/contracts/Token.sol index 8d895eeb..0e8b9215 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -60,14 +60,14 @@ contract Token is ERC20Interface { /// @param _to The address of the recipient /// @param _value The amount of token to be transferred /// @return Whether the transfer was successful or not - function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){ + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { if (balances[_from] >= _value && _value > 0 && balances[_to] + _value > balances[_to]) { - if(msg.sender==_from){ + if(msg.sender==_from) { balances[_from] -= _value; balances[_to] += _value; Transfer(_from, _to, _value); return true; - } else if (allowance(_from, msg.sender)<=_value){ + } else if (allowance(_from, msg.sender)<=_value) { allowed[_from][msg.sender] -= _value; balances[_from] -= _value; balances[_to] += _value; @@ -79,7 +79,7 @@ contract Token is ERC20Interface { } } - function refund(address _from, uint256 _value) public returns (bool success){ + function refund(address _from, uint256 _value) public returns (bool success) { if (balances[_from] >= _value && _value > 0) { balances[_from] -= _value; return true; @@ -90,7 +90,7 @@ contract Token is ERC20Interface { /// @param _owner The address from which the balance will be retrieved /// @return The balance - function balanceOf(address _owner) public constant returns (uint256 balance){ + function balanceOf(address _owner) public constant returns (uint256 balance) { return balances[_owner]; } @@ -107,9 +107,8 @@ contract Token is ERC20Interface { /// @param _owner The address of the account owning tokens /// @param _spender The address of the account able to transfer the tokens /// @return Amount of remaining tokens allowed to spent - function allowance(address _owner, address _spender) public constant returns (uint256 remaining){ + function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { return allowed[_owner][_spender]; } - } From ae508c00b9612d6229d137658a75abc375d78b4c Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 17:19:25 -0700 Subject: [PATCH 18/35] update styling --- contracts/Token.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/Token.sol b/contracts/Token.sol index 0e8b9215..4558a3f4 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -9,7 +9,6 @@ import './interfaces/ERC20Interface.sol'; */ contract Token is ERC20Interface { - // YOUR CODE HERE // we need functions from token including following: // - token.mint(amount); @@ -98,7 +97,7 @@ contract Token is ERC20Interface { /// @param _spender The address of the account able to transfer the tokens /// @param _value The amount of tokens to be approved for transfer /// @return Whether the approval was successful or not - function approve(address _spender, uint256 _value) public returns (bool success){ + function approve(address _spender, uint256 _value) public returns (bool success) { allowed[msg.sender][_spender]+=_value; Approval(msg.sender, _spender, _value); return true; From a4309ac8bad2d8020dbdb29b9c16a590467dd9ff Mon Sep 17 00:00:00 2001 From: kwanhongyap Date: Sun, 29 Oct 2017 18:56:35 -0700 Subject: [PATCH 19/35] crowdsale test added --- test/TestCrowdSale.js | 92 ++++++++++++++++++++++++++++++++++++++ test/TestCrowdSaleEnded.js | 79 ++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 test/TestCrowdSale.js create mode 100644 test/TestCrowdSaleEnded.js diff --git a/test/TestCrowdSale.js b/test/TestCrowdSale.js new file mode 100644 index 00000000..7f3eb740 --- /dev/null +++ b/test/TestCrowdSale.js @@ -0,0 +1,92 @@ +'use strict'; + +/* Add the dependencies you're testing */ +const Crowdsale = artifacts.require("./Crowdsale.sol"); +// YOUR CODE HERE + +contract('TestCrowdsale', function(accounts) { + /* Define your constant variables and instantiate constantly changing + * ones + */ + const exchangeRate = 10; + const totalSupply = 1000; + const timeLimit = 100; + const owner = accounts[0]; + const buyer1 = accounts[1]; + const buyer2 = accounts[2]; + + + let crowdsale; + // YOUR CODE HERE + + /* Do something before every `describe` method */ + beforeEach(async function() { + // YOUR CODE HERE + let c = await Crowdsale.new( + exchangeRate, + totalSupply, + timeLimit, + {from: owner}, + ); + crowdsale = c; + }); + + /* Group test cases together + * Make sure to provide descriptive strings for method arguements and + * assert statements + */ + describe('Initialization', function() { + it("TestInit", async function() { + // YOUR CODE HERE + let creator = await crowdsale.creator.call(); + let totalRaised = await crowdsale.totalRaised.call(); + let currentBalance = await crowdsale.currentBalence.call(); + let startingTime = await crowdsale.startingTime.call(); + let endingTime = await crowdsale.endingTime.call(); + assert.equal(owner, creator.valueOf(), "no creator"); + assert.equal(0, totalRaised.valueOf(), "initial raise should be 0"); + assert.equal(0, currentBalance.valueOf(), "should have 0 balance to begin with") + assert.isAtMost(startingTime.valueOf(), endingTime.valueOf(), "ending time should be more than startingTime") + }); + // YOUR CODE HERE + }); + + describe('Sale', function() { + it("TestExchange", async function() { + // YOUR CODE HERE + let wei = 100; + let token = await crowdsale.weiToToken.call(wei); + assert equal(wei*exchangeRate, token.valueOf(), "incorrect excahngerate") + }); + it("TestExchangeBack", async function() { + // YOUR CODE HERE + let token = 100; + let wei = await crowdsale.tokenToWei.call(token); + assert equal(token/exchangeRate, wei.valueOf(), "incorrect excahngerate") + }); + it("TestDelivering", async function() { + // YOUR CODE HERE + let boolean = await crowdsale.deliver.call({from: buyer1, value: 10}); + assert equal(true, boolean, "failed transaction") + let tokensold = await crowdsale.totalRaised.call(); + let curBalance = await crowdsale.currentBalance.call(); + assert equal(tokensold, 10, "different token sold amount"); + assert equal(curBalance, 10*exchangeRate, "different currentBalance"); + + }); + it("TestRefund", async function() { + let boolean await crowdsale.refund.call(10*exchangeRate, {from: buyer1}); + assert equal(true, boolean, "failed transaction"); + let tokensold = await crowdsale.totalRaised.call(); + let curBalance = await crowdsale.currentBalance.call(); + assert equal(tokensold, 0, "different token sold amount"); + assert equal(curBalance, 0, "different currentBalance"); + }); + + // YOUR CODE HERE + }); + + describe('Your string here', function() { + // YOUR CODE HERE + }); +}); \ No newline at end of file diff --git a/test/TestCrowdSaleEnded.js b/test/TestCrowdSaleEnded.js new file mode 100644 index 00000000..a80e7495 --- /dev/null +++ b/test/TestCrowdSaleEnded.js @@ -0,0 +1,79 @@ +'use strict'; + +/* Add the dependencies you're testing */ +const Crowdsale = artifacts.require("./Crowdsale.sol"); +// YOUR CODE HERE + +contract('TestCrowdsale', function(accounts) { + /* Define your constant variables and instantiate constantly changing + * ones + */ + const exchangeRate = 10; + const totalSupply = 1000; + const timeLimit = 0; + const owner = accounts[0]; + const buyer1 = accounts[1]; + const buyer2 = accounts[2]; + + + let crowdsale; + // YOUR CODE HERE + + /* Do something before every `describe` method */ + beforeEach(async function() { + // YOUR CODE HERE + let c = await Crowdsale.new( + exchangeRate, + totalSupply, + timeLimit, + {from: owner}, + ); + crowdsale = c; + }); + + /* Group test cases together + * Make sure to provide descriptive strings for method arguements and + * assert statements + */ + describe('Initialization', function() { + it("TestInit", async function() { + // YOUR CODE HERE + let creator = await crowdsale.creator.call(); + let totalRaised = await crowdsale.totalRaised.call(); + let currentBalance = await crowdsale.currentBalence.call(); + let startingTime = await crowdsale.startingTime.call(); + let endingTime = await crowdsale.endingTime.call(); + assert.equal(owner, creator.valueOf(), "no creator"); + assert.equal(0, totalRaised.valueOf(), "initial raise should be 0"); + assert.equal(0, currentBalance.valueOf(), "should have 0 balance to begin with") + assert.isAtMost(startingTime.valueOf(), endingTime.valueOf(), "ending time should be more than startingTime") + }); + // YOUR CODE HERE + }); + + describe('Sale', function() { + it("TestSaleAfterEnd", async function() { + // YOUR CODE HERE + let startTime = await crowdsale.startingTime.call(); + let endTime = await crowdsale.endingTime.call(); + while (endTime <= startTime) { + endTime = await crowdsale.endingTime.call(); + continue; + } + + let boolean = await crowdsale.deliver.call({from: buyer1, value: 10}); + assert equal(false, boolean, "buyer shouldnt be able to buy"); + let tokensold = await crowdsale.totalRaised.call(); + let curBalance = await crowdsale.currentBalance.call(); + assert equal(tokensold, 0, "different token sold amount"); + assert equal(curBalance, 0, "different currentBalance"); + + }); + + // YOUR CODE HERE + }); + + describe('Your string here', function() { + // YOUR CODE HERE + }); +}); \ No newline at end of file From bbad15c8727ce1bc7352f38971fca3575afd2328 Mon Sep 17 00:00:00 2001 From: kwanhongyap Date: Sun, 29 Oct 2017 19:15:13 -0700 Subject: [PATCH 20/35] crowdsale edited --- contracts/Crowdsale.sol | 42 ++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index 304c7e76..b0c371e4 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -2,6 +2,7 @@ pragma solidity ^0.4.15; import './Queue.sol'; import './Token.sol'; +import './utils/SafeMath.sol'; /** * @title Crowdsale @@ -11,8 +12,8 @@ import './Token.sol'; contract Crowdsale { address public creator; - uint public totalRaised; - uint public currentBalence; + uint public totalRaised; // measured in token + uint public currentBalence; // measured in wei uint private startingTime; uint private endingTime; uint public exchangeRate; @@ -43,13 +44,16 @@ contract Crowdsale { uint _timeInMinutesForFundraising) { startingTime = now; - endingTime = startingTime + (_timeInMinutesForFundraising * 1 minutes); + endingTime = SafeMath.add(startingTime, SafeMath.mul(_timeInMinutesForFundraising, 1 minutes)); + //endingTime = startingTime + (_timeInMinutesForFundraising * 1 minutes); creator = msg.sender; exchangeRate = _exhangeRate; token = new Token(_totalSupply); queue = new Queue(100); } + + function mint(uint256 amount) isCreator() { token.mint(amount); } @@ -58,35 +62,46 @@ contract Crowdsale { token.burn(amount); } - function deliver() payable saleHasNotEnded() returns (bool) { - uint tokensAmount = msg.value * exchangeRate; + function weiToToken(uint256 weiAmount) returns (uint256) { + return SafeMath.mul(weiAmount, exchangeRate); + } - if (tokensAmount > (token.totalSupply() - totalRaised)) { - revert(); + function tokenToWei(uint256 tokenAmount) returns (uint256) { + return SafeMath.div(tokenAmount, exchangeRate); + } + + function deliver() payable saleHasNotEnded() returns (bool) { + uint tokensAmount = weiToToken(msg.value); + uint difference = SafeMath.sub(token.totalSupply(), totalRaised); + if (tokensAmount > difference) { + //revert(); + msg.sender.transfer(msg.value); return false; } queue.enqueue(msg.sender); - while (queue.checkPlace() > 1) { // until first in line + while (queue.checkPlace() > 1) { // wait until being the first buyer continue; } - require( queue.checkPlace() == 1 ); + require(queue.checkPlace() == 1); queue.checkTime(); if (queue.checkPlace() == 0) { // times up - revert(); + //revert(); + msg.sender.transfer(msg.value); TokenDelivered(msg.sender, false); return false; } - while (queue.qsize() < 1) { // until at least 2 nodes in the queue + while (queue.qsize() < 1) { // make sure the buyer always have ppl behind continue; } queue.dequeue(); bool success = token.transfer(msg.sender, tokensAmount); if (success) { - currentBalence += msg.value; + currentBalence = SafeMath.add(currentBalence, msg.value); + //currentBalence += msg.value; } TokenDelivered(msg.sender, success); return success; @@ -97,7 +112,8 @@ contract Crowdsale { function refund(uint256 amount) saleHasNotEnded() returns (bool) { bool good = token.refund(msg.sender, amount); if (good) { - good = msg.sender.send(amount*exchangeRate); + uint256 refundAmount = tokenToWei(amount); + good = msg.sender.send(refundAmount); } EtherRefunded(msg.sender, good); // event return good; From 99c25889a29f9ea689759ab5335526abd376b959 Mon Sep 17 00:00:00 2001 From: kwanhongyap Date: Sun, 29 Oct 2017 19:40:58 -0700 Subject: [PATCH 21/35] crowdsale change again --- contracts/Crowdsale.sol | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index b0c371e4..01a9337a 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -86,6 +86,16 @@ contract Crowdsale { } require(queue.checkPlace() == 1); + while (queue.qsize() < 1) { // make sure the buyer always have ppl behind + queue.checkTime(); + if (queue.checkPlace() == 0) { // times up + //revert(); + msg.sender.transfer(msg.value); + TokenDelivered(msg.sender, false); + return false; + } + continue; + } queue.checkTime(); if (queue.checkPlace() == 0) { // times up //revert(); @@ -93,10 +103,6 @@ contract Crowdsale { TokenDelivered(msg.sender, false); return false; } - - while (queue.qsize() < 1) { // make sure the buyer always have ppl behind - continue; - } queue.dequeue(); bool success = token.transfer(msg.sender, tokensAmount); if (success) { From 19a642ae65aebbe0eb92ce7e825f102dcc67dce4 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 19:58:20 -0700 Subject: [PATCH 22/35] update testing --- test/TestCrowdSaleEnded.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/TestCrowdSaleEnded.js b/test/TestCrowdSaleEnded.js index a80e7495..a5ef2539 100644 --- a/test/TestCrowdSaleEnded.js +++ b/test/TestCrowdSaleEnded.js @@ -27,13 +27,13 @@ contract('TestCrowdsale', function(accounts) { totalSupply, timeLimit, {from: owner}, - ); + ); crowdsale = c; }); /* Group test cases together - * Make sure to provide descriptive strings for method arguements and - * assert statements + Make sure to provide descriptive strings for method arguements and + assert statements */ describe('Initialization', function() { it("TestInit", async function() { @@ -62,11 +62,11 @@ contract('TestCrowdsale', function(accounts) { } let boolean = await crowdsale.deliver.call({from: buyer1, value: 10}); - assert equal(false, boolean, "buyer shouldnt be able to buy"); + assert.equal(false, boolean, "buyer shouldnt be able to buy"); let tokensold = await crowdsale.totalRaised.call(); let curBalance = await crowdsale.currentBalance.call(); - assert equal(tokensold, 0, "different token sold amount"); - assert equal(curBalance, 0, "different currentBalance"); + assert.equal(tokensold, 0, "different token sold amount"); + assert.equal(curBalance, 0, "different currentBalance"); }); From 7069b2e4b5a7da61d690f98bcb71b7328d0e3dbd Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 19:58:59 -0700 Subject: [PATCH 23/35] update testing --- test/TestCrowdSale.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/TestCrowdSale.js b/test/TestCrowdSale.js index 7f3eb740..44711c06 100644 --- a/test/TestCrowdSale.js +++ b/test/TestCrowdSale.js @@ -33,7 +33,7 @@ contract('TestCrowdsale', function(accounts) { /* Group test cases together * Make sure to provide descriptive strings for method arguements and - * assert statements + * assert.statements */ describe('Initialization', function() { it("TestInit", async function() { @@ -56,31 +56,31 @@ contract('TestCrowdsale', function(accounts) { // YOUR CODE HERE let wei = 100; let token = await crowdsale.weiToToken.call(wei); - assert equal(wei*exchangeRate, token.valueOf(), "incorrect excahngerate") + assert.equal(wei*exchangeRate, token.valueOf(), "incorrect excahngerate") }); it("TestExchangeBack", async function() { // YOUR CODE HERE let token = 100; let wei = await crowdsale.tokenToWei.call(token); - assert equal(token/exchangeRate, wei.valueOf(), "incorrect excahngerate") + assert.equal(token/exchangeRate, wei.valueOf(), "incorrect excahngerate") }); it("TestDelivering", async function() { // YOUR CODE HERE let boolean = await crowdsale.deliver.call({from: buyer1, value: 10}); - assert equal(true, boolean, "failed transaction") + assert.equal(true, boolean, "failed transaction") let tokensold = await crowdsale.totalRaised.call(); let curBalance = await crowdsale.currentBalance.call(); - assert equal(tokensold, 10, "different token sold amount"); - assert equal(curBalance, 10*exchangeRate, "different currentBalance"); + assert.equal(tokensold, 10, "different token sold amount"); + assert.equal(curBalance, 10*exchangeRate, "different currentBalance"); }); it("TestRefund", async function() { let boolean await crowdsale.refund.call(10*exchangeRate, {from: buyer1}); - assert equal(true, boolean, "failed transaction"); + assert.equal(true, boolean, "failed transaction"); let tokensold = await crowdsale.totalRaised.call(); let curBalance = await crowdsale.currentBalance.call(); - assert equal(tokensold, 0, "different token sold amount"); - assert equal(curBalance, 0, "different currentBalance"); + assert.equal(tokensold, 0, "different token sold amount"); + assert.equal(curBalance, 0, "different currentBalance"); }); // YOUR CODE HERE From 7e12981ead2c07fa68c2c863268b030a25eecdc1 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 20:39:08 -0700 Subject: [PATCH 24/35] add removeContract --- contracts/Crowdsale.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index 01a9337a..3b04a46f 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -115,7 +115,7 @@ contract Crowdsale { } - function refund(uint256 amount) saleHasNotEnded() returns (bool) { + function refund(uint256 amount) public saleHasNotEnded() returns (bool) { bool good = token.refund(msg.sender, amount); if (good) { uint256 refundAmount = tokenToWei(amount); @@ -125,10 +125,14 @@ contract Crowdsale { return good; } - function withdrawFunds() saleHasEnded() isCreator() returns (bool) { + function withdrawFunds() public saleHasEnded() isCreator() returns (bool) { return creator.send(currentBalence); } + function removeContract() public isCreator() saleHasEnded() { + selfdestruct(msg.sender); + } + function () { revert(); } } From 638b01881d2fc4b5a6f4483d5e07ae1bf2ee7b41 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 20:40:27 -0700 Subject: [PATCH 25/35] up to date --- contracts/Crowdsale.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index 3b04a46f..87a916be 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -131,7 +131,7 @@ contract Crowdsale { function removeContract() public isCreator() saleHasEnded() { selfdestruct(msg.sender); - } + } function () { revert(); } From 207a59ab44701e4c37c931ab6123eb2f29eab7c1 Mon Sep 17 00:00:00 2001 From: kwanhongyap Date: Sun, 29 Oct 2017 20:53:49 -0700 Subject: [PATCH 26/35] many updates --- .DS_Store | Bin 0 -> 6148 bytes contracts/Crowdsale.sol | 15 ++++++++------- test/TestCrowdSale.js | 12 ++++++++++-- test/TestCrowdSaleEnded.js | 12 ++++++++---- 4 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..00fd3950b95ad2e585799089c604d931a6c8a1e0 GIT binary patch literal 6148 zcmeHK&1%~~5Z+DHR(38bO(4+AUIRY3NnKx6Cp{JnDhVYit`v!QL1>M%jwr^ULr#5+ zCjEJjkiJ77rMJ%PZbDM0*J8qqnEhsVc2?47?~aBs#s|~%1!DnY%m+pE+R)r1=to_U z6*uAma+!YyPO1FHj+1?v)uUj2R~0&z zMONMlJvxv@s_KE77HM@9+4T-&s>h>XV_0UV5IT&DY+qI~k-5~L{1#rLU~@Lx?)5ri zyWgF6#H`=%cErn_SMzyr=KIgLdavKUpUgjhIluV&?fZ|*EBjk;IJ%5Hb9fCu!MKN- z)2J+RRh)nqBR!xkV-?d$O_U*JH-!8}6u3y1iUIe>_t%!{spw&d0b*bo7{K#EfFgzt z8;j=XfX0*nfcP0<1Z=D&Fh)2G9X1xh1Hx@6pbh1&#Naj@#)X>~I&3W3aK>Hn!QGv? zt5CSPJFG9vbjCxA)Di>4z+DDbZ8yOD|K{KI|J@+!5d*})gJOVtd(qwiUdiRwg_pxz uD?mSjqTsy7q6vY Date: Sun, 29 Oct 2017 22:11:13 -0700 Subject: [PATCH 27/35] some tests --- build/contracts/Crowdsale.json | 283 +++++++++++++++++++++ build/contracts/ERC20Interface.json | 176 +++++++++++++ build/contracts/Math.json | 8 + build/contracts/Migrations.json | 79 ++++++ build/contracts/Queue.json | 113 +++++++++ build/contracts/SafeMath.json | 8 + build/contracts/Token.json | 373 ++++++++++++++++++++++++++++ contracts/Crowdsale.sol | 8 +- contracts/Token.sol | 25 +- test/TestToken.js | 43 ++++ 10 files changed, 1103 insertions(+), 13 deletions(-) create mode 100644 build/contracts/Crowdsale.json create mode 100644 build/contracts/ERC20Interface.json create mode 100644 build/contracts/Math.json create mode 100644 build/contracts/Migrations.json create mode 100644 build/contracts/Queue.json create mode 100644 build/contracts/SafeMath.json create mode 100644 build/contracts/Token.json create mode 100644 test/TestToken.js diff --git a/build/contracts/Crowdsale.json b/build/contracts/Crowdsale.json new file mode 100644 index 00000000..7634f93c --- /dev/null +++ b/build/contracts/Crowdsale.json @@ -0,0 +1,283 @@ +{ + "contract_name": "Crowdsale", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "creator", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdrawFunds", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "refund", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "currentBalence", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalRaised", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "queue", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "deliver", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": true, + "type": "function" + }, + { + "inputs": [ + { + "name": "_exhangeRate", + "type": "uint256" + }, + { + "name": "_totalSupply", + "type": "uint256" + }, + { + "name": "_timeInMinutesForFundraising", + "type": "uint256" + } + ], + "payable": false, + "type": "constructor" + }, + { + "payable": false, + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "name": "status", + "type": "bool" + } + ], + "name": "TokenDelivered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "name": "status", + "type": "bool" + } + ], + "name": "EtherRefunded", + "type": "event" + } + ], + "unlinked_binary": "0x6060604052341561000f57600080fd5b6040516060806115568339810160405280805191906020018051919060200180519150505b426003819055603c82020160045560008054600160a060020a03191633600160a060020a031617905560058390558161006b6100f6565b908152602001604051809103906000f080151561008757600080fd5b60068054600160a060020a031916600160a060020a039290921691909117905560646100b1610106565b908152602001604051809103906000f08015156100cd57600080fd5b60078054600160a060020a031916600160a060020a03929092169190911790555b505050610116565b60405161066380610a5383390190565b6040516104a0806110b683390190565b61092e806101256000396000f300606060405236156100885763ffffffff60e060020a60003504166302d05d3f811461009b57806324600fc3146100ca578063278ecde1146100f15780633ba0b9a91461011b57806342966c681461014057806384b2142b14610158578063a0712d681461017d578063c5c4744c14610195578063e10d29ee146101ba578063fd3e50a7146101e9575b341561009357600080fd5b5b600080fd5b005b34156100a657600080fd5b6100ae610205565b604051600160a060020a03909116815260200160405180910390f35b34156100d557600080fd5b6100dd610214565b604051901515815260200160405180910390f35b34156100fc57600080fd5b6100dd600435610275565b604051901515815260200160405180910390f35b341561012657600080fd5b61012e610395565b60405190815260200160405180910390f35b341561014b57600080fd5b61009960043561039b565b005b341561016357600080fd5b61012e610417565b60405190815260200160405180910390f35b341561018857600080fd5b61009960043561041d565b005b34156101a057600080fd5b61012e610499565b60405190815260200160405180910390f35b34156101c557600080fd5b6100ae61049f565b604051600160a060020a03909116815260200160405180910390f35b6100dd6104ae565b604051901515815260200160405180910390f35b600054600160a060020a031681565b600454600090421161022557600080fd5b60005433600160a060020a0390811691161461024057600080fd5b600054600254600160a060020a039091169080156108fc0290604051600060405180830381858888f19450505050505b5b5b90565b6000804260035410801561028a575060045442105b151561029557600080fd5b600654600160a060020a031663410085df338560006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b15156102f457600080fd5b6102c65a03f1151561030557600080fd5b505050604051805191505080156103445733600160a060020a03166108fc60055485029081150290604051600060405180830381858888f19450505050505b7ff252967651cc00909ef5a4a48ce7be5929b85746b9d3d022c4bd8900a1ab1f243382604051600160a060020a039092168252151560208201526040908101905180910390a18091505b5b50919050565b60055481565b60005433600160a060020a039081169116146103b657600080fd5b600654600160a060020a03166342966c688260405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b15156103fe57600080fd5b6102c65a03f1151561040f57600080fd5b5050505b5b50565b60025481565b60005433600160a060020a0390811691161461043857600080fd5b600654600160a060020a031663a0712d688260405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b15156103fe57600080fd5b6102c65a03f1151561040f57600080fd5b5050505b5b50565b60015481565b600754600160a060020a031681565b6000806000426003541080156104c5575060045442105b15156104d057600080fd5b60055460015460065434909202935090600160a060020a03166318160ddd6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561052557600080fd5b6102c65a03f1151561053657600080fd5b505050604051805190500382111561054d57600080fd5b600754600160a060020a0316638f807f6b3360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401600060405180830381600087803b151561059d57600080fd5b6102c65a03f115156105ae57600080fd5b5050505b600754600190600160a060020a031663ad7d59fc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156105fd57600080fd5b6102c65a03f1151561060e57600080fd5b5050506040518051905060ff161115610626576105b2565b600754600160a060020a031663ad7d59fc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561066e57600080fd5b6102c65a03f1151561067f57600080fd5b5050506040518051905060ff16600114151561069a57600080fd5b600754600160a060020a031663e0c6190d6040518163ffffffff1660e060020a028152600401600060405180830381600087803b15156106d957600080fd5b6102c65a03f115156106ea57600080fd5b5050600754600160a060020a0316905063ad7d59fc6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b151561073657600080fd5b6102c65a03f1151561074757600080fd5b505050604051805160ff161515905061075f57600080fd5b5b600754600190600160a060020a0316633e3c9eae6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156107ab57600080fd5b6102c65a03f115156107bc57600080fd5b5050506040518051905060ff1610156107d45761075f565b600754600160a060020a031663957908d16040518163ffffffff1660e060020a028152600401600060405180830381600087803b151561081357600080fd5b6102c65a03f1151561082457600080fd5b5050600654600160a060020a0316905063a9059cbb338460006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561088757600080fd5b6102c65a03f1151561089857600080fd5b505050604051805191505080156108b25760028054340190555b7f41c2f4225ceb1479771ee59967887abb5a42980e43535172ca3445699dbeebbf3382604051600160a060020a039092168252151560208201526040908101905180910390a18092505b5b5050905600a165627a7a72305820aca5fb09318b1d059941b23fc9631ee98af57e7bb2ca3eaddbaa8cd9cf0f645900296060604052341561000f57600080fd5b604051602080610663833981016040528080519150505b60008190555b505b6106268061003d6000396000f300606060405236156100965763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461009b57806318160ddd146100d157806323b872dd146100f6578063410085df1461013257806342966c681461016857806370a0823114610180578063a0712d68146101b1578063a9059cbb146101c9578063dd62ed3e146101ff575b600080fd5b34156100a657600080fd5b6100bd600160a060020a0360043516602435610236565b604051901515815260200160405180910390f35b34156100dc57600080fd5b6100e46102a6565b60405190815260200160405180910390f35b341561010157600080fd5b6100bd600160a060020a03600435811690602435166044356102ac565b604051901515815260200160405180910390f35b341561013d57600080fd5b6100bd600160a060020a0360043516602435610433565b604051901515815260200160405180910390f35b341561017357600080fd5b61017e600435610498565b005b341561018b57600080fd5b6100e4600160a060020a03600435166104d8565b60405190815260200160405180910390f35b34156101bc57600080fd5b61017e6004356104f7565b005b34156101d457600080fd5b6100bd600160a060020a0360043516602435610503565b604051901515815260200160405180910390f35b341561020a57600080fd5b6100e4600160a060020a03600435811690602435166105cd565b60405190815260200160405180910390f35b600160a060020a03338116600081815260026020908152604080832094871680845294909152808220805486019055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a35060015b92915050565b60005481565b600160a060020a0383166000908152600160205260408120548290108015906102d55750600082115b80156102fa5750600160a060020a038316600090815260016020526040902054828101115b156104275783600160a060020a031633600160a060020a0316141561038657600160a060020a038085166000818152600160205260408082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600161042b565b8161039185336105cd565b1161042157600160a060020a038085166000818152600260209081526040808320338616845282528083208054889003905583835260019091528082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600161042b565b5b61042b565b5060005b5b9392505050565b600160a060020a03821660009081526001602052604081205482901080159061045c5750600082115b156104895750600160a060020a0382166000908152600160208190526040909120805483900390556102a0565b5060006102a0565b5b92915050565b6000805482900390557fb90306ad06b2a6ff86ddc9327db583062895ef6540e62dc50add009db5b356eb8160405190815260200160405180910390a15b50565b600160a060020a0381166000908152600160205260409020545b919050565b60008054820190555b50565b600160a060020a03331660009081526001602052604081205482901080159061052c5750600082115b80156105515750600160a060020a038316600090815260016020526040902054828101115b156105c357600160a060020a033381166000818152600160205260408082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060016102a0565b5060005b92915050565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b929150505600a165627a7a723058203bd278523b029ba6358fece3218519618710b8378b0b83fe7130f3c54585a8c2002960606040526000805460ff19166005179055341561001c57600080fd5b6040516020806104a0833981016040528080519150505b6002805460ff1916905560018190555b505b61044c806100546000396000f300606060405236156100805763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631e22314381146100855780633e3c9eae146100b45780638f807f6b146100dd578063957908d1146100fe578063ad7d59fc14610113578063e0c6190d1461013c578063f2a75fe414610151575b600080fd5b341561009057600080fd5b610098610178565b604051600160a060020a03909116815260200160405180910390f35b34156100bf57600080fd5b6100c76101c2565b60405160ff909116815260200160405180910390f35b34156100e857600080fd5b6100fc600160a060020a03600435166101cc565b005b341561010957600080fd5b6100fc610278565b005b341561011e57600080fd5b6100c76102e7565b60405160ff909116815260200160405180910390f35b341561014757600080fd5b6100fc610354565b005b341561015c57600080fd5b6101646103a4565b604051901515815260200160405180910390f35b60025460009060ff16819011156101bb5760038054600090811061019857fe5b906000526020600020906002020160005b5054600160a060020a031690506101bf565b5060005b90565b60025460ff165b90565b60005460025460ff9182169116106101e357600080fd5b60038054600181016101f583826103af565b916000526020600020906002020160005b60408051908101604052600160a060020a03851681524260208201529190508151815473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039190911617815560208201516001918201556002805460ff19811660ff9182169093011691909117905550505b50565b600254600060ff90911611156102e45760038054600090811061029757fe5b906000526020600020906002020160005b50805473ffffffffffffffffffffffffffffffffffffffff1916815560006001909101556002805460ff808216600019011660ff199091161790555b5b565b6000805b60025460ff908116908216101561034b5733600160a060020a031660038260ff1681548110151561031857fe5b906000526020600020906002020160005b5054600160a060020a0316141561034257809150610350565b5b6001016102eb565b600091505b5090565b600254600060ff9091161180156103935750426001546003600081548110151561037a57fe5b906000526020600020906002020160005b506001015401105b156102e4576102e4610278565b5b5b565b60025460ff16155b90565b8154818355818115116103db576002028160020283600052602060002091820191016103db91906103e1565b5b505050565b6101bf91905b8082111561035057805473ffffffffffffffffffffffffffffffffffffffff19168155600060018201556002016103e7565b5090565b905600a165627a7a72305820f5706623c3ea06a14b7c3d6b40fe3ac5596bec4e716bca83a051c0113bf66a690029", + "networks": { + "1509327668930": { + "events": { + "0x41c2f4225ceb1479771ee59967887abb5a42980e43535172ca3445699dbeebbf": { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "name": "status", + "type": "bool" + } + ], + "name": "TokenDelivered", + "type": "event" + }, + "0xf252967651cc00909ef5a4a48ce7be5929b85746b9d3d022c4bd8900a1ab1f24": { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "name": "status", + "type": "bool" + } + ], + "name": "EtherRefunded", + "type": "event" + } + }, + "links": {}, + "address": "0x54c1bf462bd6ad80f2ec63784ec35759e66ecba3", + "updated_at": 1509327705376 + }, + "1509337117897": { + "events": { + "0x41c2f4225ceb1479771ee59967887abb5a42980e43535172ca3445699dbeebbf": { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "name": "status", + "type": "bool" + } + ], + "name": "TokenDelivered", + "type": "event" + }, + "0xf252967651cc00909ef5a4a48ce7be5929b85746b9d3d022c4bd8900a1ab1f24": { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "name": "status", + "type": "bool" + } + ], + "name": "EtherRefunded", + "type": "event" + } + }, + "links": {}, + "address": "0x29fdc7fa8b7bed0a26ec624c5a7a2319da6be0d0", + "updated_at": 1509337129588 + } + }, + "schema_version": "0.0.5", + "updated_at": 1509337129588 +} \ No newline at end of file diff --git a/build/contracts/ERC20Interface.json b/build/contracts/ERC20Interface.json new file mode 100644 index 00000000..438c2d38 --- /dev/null +++ b/build/contracts/ERC20Interface.json @@ -0,0 +1,176 @@ +{ + "contract_name": "ERC20Interface", + "abi": [ + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "remaining", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + } + ], + "unlinked_binary": "0x", + "networks": {}, + "schema_version": "0.0.5", + "updated_at": 1509337110556 +} \ No newline at end of file diff --git a/build/contracts/Math.json b/build/contracts/Math.json new file mode 100644 index 00000000..50c22c66 --- /dev/null +++ b/build/contracts/Math.json @@ -0,0 +1,8 @@ +{ + "contract_name": "Math", + "abi": [], + "unlinked_binary": "0x60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00a165627a7a72305820eb855728139403df615f8e482c318da4945731be87bdeb0e632e84f60ec384f20029", + "networks": {}, + "schema_version": "0.0.5", + "updated_at": 1509327704464 +} \ No newline at end of file diff --git a/build/contracts/Migrations.json b/build/contracts/Migrations.json new file mode 100644 index 00000000..61d52701 --- /dev/null +++ b/build/contracts/Migrations.json @@ -0,0 +1,79 @@ +{ + "contract_name": "Migrations", + "abi": [ + { + "constant": false, + "inputs": [ + { + "name": "new_address", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "last_completed_migration", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "completed", + "type": "uint256" + } + ], + "name": "setCompleted", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "inputs": [], + "payable": false, + "type": "constructor" + } + ], + "unlinked_binary": "0x6060604052341561000f57600080fd5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101e58061003c6000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630900f010811461005e578063445df0ac1461007f5780638da5cb5b146100a4578063fdacd576146100d3575b600080fd5b341561006957600080fd5b61007d600160a060020a03600435166100eb565b005b341561008a57600080fd5b610092610182565b60405190815260200160405180910390f35b34156100af57600080fd5b6100b7610188565b604051600160a060020a03909116815260200160405180910390f35b34156100de57600080fd5b61007d600435610197565b005b6000805433600160a060020a039081169116141561017c5781905080600160a060020a031663fdacd5766001546040517c010000000000000000000000000000000000000000000000000000000063ffffffff84160281526004810191909152602401600060405180830381600087803b151561016757600080fd5b6102c65a03f1151561017857600080fd5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a03908116911614156101b45760018190555b5b5b505600a165627a7a72305820fa6c296ebecbcd435b3e1a79ab91aeceb41aeae9d1a346db95530ee00a20c6a80029", + "networks": { + "1509327668930": { + "events": {}, + "links": {}, + "address": "0x4ab54ed565a537e0495552c05a5700c255bfe68f", + "updated_at": 1509327705382 + }, + "1509337117897": { + "events": {}, + "links": {}, + "address": "0x2772684b8a88b4c1d7c02e70bf1fe1e06c551b40", + "updated_at": 1509337129593 + } + }, + "schema_version": "0.0.5", + "updated_at": 1509337129593 +} \ No newline at end of file diff --git a/build/contracts/Queue.json b/build/contracts/Queue.json new file mode 100644 index 00000000..061512ef --- /dev/null +++ b/build/contracts/Queue.json @@ -0,0 +1,113 @@ +{ + "contract_name": "Queue", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "getFirst", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "qsize", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "addr", + "type": "address" + } + ], + "name": "enqueue", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "dequeue", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "checkPlace", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "checkTime", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "empty", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "inputs": [ + { + "name": "_timeLimit", + "type": "uint256" + } + ], + "payable": false, + "type": "constructor" + } + ], + "unlinked_binary": "0x60606040526000805460ff19166005179055341561001c57600080fd5b6040516020806104a0833981016040528080519150505b6002805460ff1916905560018190555b505b61044c806100546000396000f300606060405236156100805763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631e22314381146100855780633e3c9eae146100b45780638f807f6b146100dd578063957908d1146100fe578063ad7d59fc14610113578063e0c6190d1461013c578063f2a75fe414610151575b600080fd5b341561009057600080fd5b610098610178565b604051600160a060020a03909116815260200160405180910390f35b34156100bf57600080fd5b6100c76101c2565b60405160ff909116815260200160405180910390f35b34156100e857600080fd5b6100fc600160a060020a03600435166101cc565b005b341561010957600080fd5b6100fc610278565b005b341561011e57600080fd5b6100c76102e7565b60405160ff909116815260200160405180910390f35b341561014757600080fd5b6100fc610354565b005b341561015c57600080fd5b6101646103a4565b604051901515815260200160405180910390f35b60025460009060ff16819011156101bb5760038054600090811061019857fe5b906000526020600020906002020160005b5054600160a060020a031690506101bf565b5060005b90565b60025460ff165b90565b60005460025460ff9182169116106101e357600080fd5b60038054600181016101f583826103af565b916000526020600020906002020160005b60408051908101604052600160a060020a03851681524260208201529190508151815473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039190911617815560208201516001918201556002805460ff19811660ff9182169093011691909117905550505b50565b600254600060ff90911611156102e45760038054600090811061029757fe5b906000526020600020906002020160005b50805473ffffffffffffffffffffffffffffffffffffffff1916815560006001909101556002805460ff808216600019011660ff199091161790555b5b565b6000805b60025460ff908116908216101561034b5733600160a060020a031660038260ff1681548110151561031857fe5b906000526020600020906002020160005b5054600160a060020a0316141561034257809150610350565b5b6001016102eb565b600091505b5090565b600254600060ff9091161180156103935750426001546003600081548110151561037a57fe5b906000526020600020906002020160005b506001015401105b156102e4576102e4610278565b5b5b565b60025460ff16155b90565b8154818355818115116103db576002028160020283600052602060002091820191016103db91906103e1565b5b505050565b6101bf91905b8082111561035057805473ffffffffffffffffffffffffffffffffffffffff19168155600060018201556002016103e7565b5090565b905600a165627a7a72305820f5706623c3ea06a14b7c3d6b40fe3ac5596bec4e716bca83a051c0113bf66a690029", + "networks": { + "1509327668930": { + "events": {}, + "links": {}, + "address": "0xe3b08d118fdb4f6d5afceb5be95df1e44440e762", + "updated_at": 1509327705379 + }, + "1509337117897": { + "events": {}, + "links": {}, + "address": "0x0e14928a4e352bca36bc683b5a9465a6c77454db", + "updated_at": 1509337129592 + } + }, + "schema_version": "0.0.5", + "updated_at": 1509337129592 +} \ No newline at end of file diff --git a/build/contracts/SafeMath.json b/build/contracts/SafeMath.json new file mode 100644 index 00000000..047a9c4f --- /dev/null +++ b/build/contracts/SafeMath.json @@ -0,0 +1,8 @@ +{ + "contract_name": "SafeMath", + "abi": [], + "unlinked_binary": "0x60606040523415600e57600080fd5b5b603680601c6000396000f30060606040525b600080fd00a165627a7a723058206253a4a0942398dc417fdfc4a5f89e1806e15f4b38fac8b691b39e81ea2622bf0029", + "networks": {}, + "schema_version": "0.0.5", + "updated_at": 1509327704464 +} \ No newline at end of file diff --git a/build/contracts/Token.json b/build/contracts/Token.json new file mode 100644 index 00000000..28dfc025 --- /dev/null +++ b/build/contracts/Token.json @@ -0,0 +1,373 @@ +{ + "contract_name": "Token", + "abi": [ + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "refund", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "burn", + "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": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "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" + }, + { + "inputs": [ + { + "name": "_totalSupplyAmount", + "type": "uint256" + } + ], + "payable": false, + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Burned", + "type": "event" + } + ], + "unlinked_binary": "0x6060604052341561000f57600080fd5b604051602080610682833981016040528080519150505b60008190555b505b6106458061003d6000396000f300606060405236156100965763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461009b57806318160ddd146100d157806323b872dd146100f6578063410085df1461013257806342966c681461016857806370a0823114610180578063a0712d68146101b1578063a9059cbb146101c9578063dd62ed3e146101ff575b600080fd5b34156100a657600080fd5b6100bd600160a060020a0360043516602435610236565b604051901515815260200160405180910390f35b34156100dc57600080fd5b6100e46102a6565b60405190815260200160405180910390f35b341561010157600080fd5b6100bd600160a060020a03600435811690602435166044356102ac565b604051901515815260200160405180910390f35b341561013d57600080fd5b6100bd600160a060020a0360043516602435610433565b604051901515815260200160405180910390f35b341561017357600080fd5b61017e600435610498565b005b341561018b57600080fd5b6100e4600160a060020a03600435166104f7565b60405190815260200160405180910390f35b34156101bc57600080fd5b61017e600435610516565b005b34156101d457600080fd5b6100bd600160a060020a0360043516602435610522565b604051901515815260200160405180910390f35b341561020a57600080fd5b6100e4600160a060020a03600435811690602435166105ec565b60405190815260200160405180910390f35b600160a060020a03338116600081815260026020908152604080832094871680845294909152808220805486019055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a35060015b92915050565b60005481565b600160a060020a0383166000908152600160205260408120548290108015906102d55750600082115b80156102fa5750600160a060020a038316600090815260016020526040902054828101115b156104275783600160a060020a031633600160a060020a0316141561038657600160a060020a038085166000818152600160205260408082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600161042b565b8161039185336105ec565b1161042157600160a060020a038085166000818152600260209081526040808320338616845282528083208054889003905583835260019091528082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600161042b565b5b61042b565b5060005b5b9392505050565b600160a060020a03821660009081526001602052604081205482901080159061045c5750600082115b156104895750600160a060020a0382166000908152600160208190526040909120805483900390556102a0565b5060006102a0565b5b92915050565b600160a060020a0333166000908152600160205260408082208054849003905581548390039091557fd83c63197e8e676d80ab0122beba9a9d20f3828839e9a1d6fe81d242e9cd7e6e9082905190815260200160405180910390a15b50565b600160a060020a0381166000908152600160205260409020545b919050565b60008054820190555b50565b600160a060020a03331660009081526001602052604081205482901080159061054b5750600082115b80156105705750600160a060020a038316600090815260016020526040902054828101115b156105e257600160a060020a033381166000818152600160205260408082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060016102a0565b5060005b92915050565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b929150505600a165627a7a723058205ec42460f00182feefcbd720bda85d33d18fc051862c2cc38570e4c4596b58d50029", + "networks": { + "1509327668930": { + "events": { + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { + "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" + }, + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + "0xb90306ad06b2a6ff86ddc9327db583062895ef6540e62dc50add009db5b356eb": { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event" + } + }, + "links": {}, + "address": "0xdfab00cb6ed935bc6621ae4eeced6502c0b175d7", + "updated_at": 1509327705379 + }, + "1509337117897": { + "events": { + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { + "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" + }, + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + "0xd83c63197e8e676d80ab0122beba9a9d20f3828839e9a1d6fe81d242e9cd7e6e": { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Burned", + "type": "event" + } + }, + "links": {}, + "address": "0x01b8acb538ba120d6e6da1bb17dbfe8608c183e6", + "updated_at": 1509337129593 + } + }, + "schema_version": "0.0.5", + "updated_at": 1509337129593 +} \ No newline at end of file diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index 304c7e76..1a342c00 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -38,9 +38,9 @@ contract Crowdsale { } function Crowdsale( - uint256 _exhangeRate, - uint256 _totalSupply, - uint _timeInMinutesForFundraising) + uint256 _exhangeRate, + uint256 _totalSupply, + uint _timeInMinutesForFundraising) { startingTime = now; endingTime = startingTime + (_timeInMinutesForFundraising * 1 minutes); @@ -54,7 +54,7 @@ contract Crowdsale { token.mint(amount); } - function burn(uint256 amount) isCreator() { + function burn(uint256 amount){ token.burn(amount); } diff --git a/contracts/Token.sol b/contracts/Token.sol index 8d895eeb..dd0b45c9 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -20,7 +20,7 @@ contract Token is ERC20Interface { // ---> these 5 functions event Transfer(address indexed _from, address indexed _to, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value); - event Burn(uint256 _value); + event Burned(uint256 _value, uint256 _total); // Balances for each account mapping(address => uint256) private balances; @@ -28,17 +28,23 @@ contract Token is ERC20Interface { // Owner of account approves the transfer of an amount to another account mapping(address => mapping (address => uint256)) allowed; - function Token(uint _totalSupplyAmount) { + function Token(uint _totalSupplyAmount) public{ totalSupply = _totalSupplyAmount; } - function mint(uint256 amount) { - totalSupply += amount; + function totalSupply() public{ + return totalSupply; } - function burn(uint256 amount) { - totalSupply -= amount; - Burn(amount); + function mint(uint256 _amount) public{ + balances[msg.sender] = balances[msg.sender] + _amount; + totalSupply = totalSupply + _amount; + } + + function burn(uint256 _amount) public{ + balances[msg.sender] = balances[msg.sender] - _amount; + totalSupply = totalSupply - _amount; + Burned(_amount, totalSupply); } /// @notice send `_value` token to `_to` from `msg.sender` @@ -51,8 +57,9 @@ contract Token is ERC20Interface { balances[_to] += _value; Transfer(msg.sender, _to, _value); return true; + } else { + return false; } - return false; } /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` @@ -111,5 +118,5 @@ contract Token is ERC20Interface { return allowed[_owner][_spender]; } - + } diff --git a/test/TestToken.js b/test/TestToken.js new file mode 100644 index 00000000..2ff7ba17 --- /dev/null +++ b/test/TestToken.js @@ -0,0 +1,43 @@ + +const Crowdsale = artifacts.require("./Crowdsale.sol"); +const Token = artifacts.require("./Token.sol"); + +contract('TestToken', function(accounts){ + let token; + beforeEach(async function() { + let t = await Token.new(0); + token = t; + }); + + describe('Test token operations', function(){ + it("Testing minting and burning", async function() { + let total = await token.totalSupply.call(); + assert.equal(total , 0, "totalSupply is initialized at 0"); + await token.mint(5); + total = await token.totalSupply.call(); + assert.equal(total , 5, "totalSupply should equal 5"); + await token.burn(2); + total = await token.totalSupply.call(); + assert.equal(total , 3, "totalSupply should equal 3"); + }), + it("Testing transfer", async function() { + await token.mint(10); + await token.transfer(accounts[1], 3); + console.log(await token.balanceOf(accounts[1])); + await token.transfer(accounts[2], 4); + console.log(await token.balanceOf(accounts[2])); + total1 = await token.balanceOf(accounts[1]); + assert.equal(total1 , 3, "address 0 should have 3 in its account"); + total2 = await token.balanceOf(accounts[2]); + assert.equal(total2 , 4, "address 1 should have 4 in its account"); + }) + it("Testing transferFrom", async function() { + await token.mint(10); + await token.approve(accounts[1], 4); + assert.equal(token.allowance(accounts[0], accounts[1]) , 4, "address 2 should have 4 in its account"); + await token.transferFrom(accounts[0], accounts[2], 4).call({from: accounts[1]}); + transfered = await token.balanceOf(accounts[2]); + assert.equal(transfered , 4, "address 2 should have 4 in its account"); + }) + }); +}); From 4afe296cf46783471b74d8d252e5d946be5d854f Mon Sep 17 00:00:00 2001 From: Jesse Paterson Date: Sun, 29 Oct 2017 22:11:56 -0700 Subject: [PATCH 28/35] updated totalSupply() --- contracts/Token.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Token.sol b/contracts/Token.sol index dd0b45c9..155d5f3a 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -32,7 +32,7 @@ contract Token is ERC20Interface { totalSupply = _totalSupplyAmount; } - function totalSupply() public{ + function totalSupply() public returns (uint256){ return totalSupply; } From 8bd3f846efa85a4e2d721db9135a95aa89defb22 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 22:12:30 -0700 Subject: [PATCH 29/35] add totalSupply to Toekn --- contracts/Token.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/Token.sol b/contracts/Token.sol index 4558a3f4..940e21c8 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -17,6 +17,8 @@ contract Token is ERC20Interface { // - token.transfer(msg.sender, tokensAmount); // - token.refund(msg.sender, amount); // ---> these 5 functions + uint totalSupply; + event Transfer(address indexed _from, address indexed _to, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value); event Burn(uint256 _value); From c65c262fbf965907b5ee68453b3d42c49484e741 Mon Sep 17 00:00:00 2001 From: Jesse Paterson Date: Sun, 29 Oct 2017 22:28:34 -0700 Subject: [PATCH 30/35] totalToken implemented instead --- contracts/Token.sol | 21 +++++++++++---------- test/TestToken.js | 21 +++++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/contracts/Token.sol b/contracts/Token.sol index 13912a10..5195d81e 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -9,6 +9,7 @@ import './interfaces/ERC20Interface.sol'; */ contract Token is ERC20Interface { + // YOUR CODE HERE // we need functions from token including following: // - token.mint(amount); @@ -17,8 +18,6 @@ contract Token is ERC20Interface { // - token.transfer(msg.sender, tokensAmount); // - token.refund(msg.sender, amount); // ---> these 5 functions - uint totalSupply; - event Transfer(address indexed _from, address indexed _to, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value); event Burned(uint256 _value, uint256 _total); @@ -33,7 +32,7 @@ contract Token is ERC20Interface { totalSupply = _totalSupplyAmount; } - function totalSupply() public returns (uint256){ + function totalToken() public returns (uint256){ return totalSupply; } @@ -68,14 +67,14 @@ contract Token is ERC20Interface { /// @param _to The address of the recipient /// @param _value The amount of token to be transferred /// @return Whether the transfer was successful or not - function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){ if (balances[_from] >= _value && _value > 0 && balances[_to] + _value > balances[_to]) { - if(msg.sender==_from) { + if(msg.sender==_from){ balances[_from] -= _value; balances[_to] += _value; Transfer(_from, _to, _value); return true; - } else if (allowance(_from, msg.sender)<=_value) { + } else if (allowance(_from, msg.sender)<=_value){ allowed[_from][msg.sender] -= _value; balances[_from] -= _value; balances[_to] += _value; @@ -87,7 +86,7 @@ contract Token is ERC20Interface { } } - function refund(address _from, uint256 _value) public returns (bool success) { + function refund(address _from, uint256 _value) public returns (bool success){ if (balances[_from] >= _value && _value > 0) { balances[_from] -= _value; return true; @@ -98,7 +97,7 @@ contract Token is ERC20Interface { /// @param _owner The address from which the balance will be retrieved /// @return The balance - function balanceOf(address _owner) public constant returns (uint256 balance) { + function balanceOf(address _owner) public constant returns (uint256 balance){ return balances[_owner]; } @@ -106,7 +105,7 @@ contract Token is ERC20Interface { /// @param _spender The address of the account able to transfer the tokens /// @param _value The amount of tokens to be approved for transfer /// @return Whether the approval was successful or not - function approve(address _spender, uint256 _value) public returns (bool success) { + function approve(address _spender, uint256 _value) public returns (bool success){ allowed[msg.sender][_spender]+=_value; Approval(msg.sender, _spender, _value); return true; @@ -115,7 +114,9 @@ contract Token is ERC20Interface { /// @param _owner The address of the account owning tokens /// @param _spender The address of the account able to transfer the tokens /// @return Amount of remaining tokens allowed to spent - function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { + function allowance(address _owner, address _spender) public constant returns (uint256 remaining){ return allowed[_owner][_spender]; } + + } diff --git a/test/TestToken.js b/test/TestToken.js index 2ff7ba17..25519396 100644 --- a/test/TestToken.js +++ b/test/TestToken.js @@ -11,21 +11,22 @@ contract('TestToken', function(accounts){ describe('Test token operations', function(){ it("Testing minting and burning", async function() { - let total = await token.totalSupply.call(); - assert.equal(total , 0, "totalSupply is initialized at 0"); - await token.mint(5); - total = await token.totalSupply.call(); - assert.equal(total , 5, "totalSupply should equal 5"); - await token.burn(2); - total = await token.totalSupply.call(); - assert.equal(total , 3, "totalSupply should equal 3"); + let total = await token.totalSupply.call(); + assert.equal(total , 0, "totalSupply is initialized at 0"); + await token.mint(5); + total = await token.totalSupply.call(); + console.log(token.totalSupply); + assert.equal(total , 5, "totalSupply should equal 5"); + await token.burn(2); + total = await token.totalSupply.call(); + assert.equal(total , 3, "totalSupply should equal 3"); }), it("Testing transfer", async function() { await token.mint(10); await token.transfer(accounts[1], 3); - console.log(await token.balanceOf(accounts[1])); + //console.log(await token.balanceOf(accounts[1])); await token.transfer(accounts[2], 4); - console.log(await token.balanceOf(accounts[2])); + //console.log(await token.balanceOf(accounts[2])); total1 = await token.balanceOf(accounts[1]); assert.equal(total1 , 3, "address 0 should have 3 in its account"); total2 = await token.balanceOf(accounts[2]); From 07f6d07313c2d7911707d3a30c276dc36912d3f8 Mon Sep 17 00:00:00 2001 From: Jesse Paterson Date: Sun, 29 Oct 2017 22:45:18 -0700 Subject: [PATCH 31/35] Token tested and working --- contracts/Token.sol | 2 +- test/TestToken.js | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/contracts/Token.sol b/contracts/Token.sol index 5195d81e..8b9c0a24 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -88,7 +88,7 @@ contract Token is ERC20Interface { function refund(address _from, uint256 _value) public returns (bool success){ if (balances[_from] >= _value && _value > 0) { - balances[_from] -= _value; + balances[_from] = balances[_from] - _value; return true; } else { return false; diff --git a/test/TestToken.js b/test/TestToken.js index 25519396..72440b52 100644 --- a/test/TestToken.js +++ b/test/TestToken.js @@ -15,7 +15,7 @@ contract('TestToken', function(accounts){ assert.equal(total , 0, "totalSupply is initialized at 0"); await token.mint(5); total = await token.totalSupply.call(); - console.log(token.totalSupply); + //console.log(token.totalSupply); assert.equal(total , 5, "totalSupply should equal 5"); await token.burn(2); total = await token.totalSupply.call(); @@ -27,18 +27,28 @@ contract('TestToken', function(accounts){ //console.log(await token.balanceOf(accounts[1])); await token.transfer(accounts[2], 4); //console.log(await token.balanceOf(accounts[2])); - total1 = await token.balanceOf(accounts[1]); + let total1 = await token.balanceOf(accounts[1]); assert.equal(total1 , 3, "address 0 should have 3 in its account"); - total2 = await token.balanceOf(accounts[2]); + let total2 = await token.balanceOf(accounts[2]); assert.equal(total2 , 4, "address 1 should have 4 in its account"); }) it("Testing transferFrom", async function() { await token.mint(10); await token.approve(accounts[1], 4); - assert.equal(token.allowance(accounts[0], accounts[1]) , 4, "address 2 should have 4 in its account"); - await token.transferFrom(accounts[0], accounts[2], 4).call({from: accounts[1]}); - transfered = await token.balanceOf(accounts[2]); + let allowed = await token.allowance(accounts[0], accounts[1]); + assert.equal(allowed , 4, "address 1 should be allowed to transfer 4 from address 0's account"); + await token.transferFrom(accounts[0], accounts[2], 4); + let transfered = await token.balanceOf(accounts[2]); assert.equal(transfered , 4, "address 2 should have 4 in its account"); }) + it("Testing refund", async function() { + await token.mint(10); + await token.refund(accounts[0], 3); + let afterRefund = await token.balanceOf(accounts[0]); + assert.equal(afterRefund , 7, "should have removed 3 from the account"); + await token.refund(accounts[0], 9); + afterRefund = await token.balanceOf(accounts[0]); + assert.equal(afterRefund , 7, false, "can't refund more than is in the account"); + }) }); }); From 4603a21a3d184dd9753437bab23408a121a4fd26 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 23:15:45 -0700 Subject: [PATCH 32/35] fix checkPlace --- contracts/Crowdsale.sol | 8 ++++---- contracts/Queue.sol | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index c5f8dbda..5dc40ebe 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -82,14 +82,14 @@ contract Crowdsale { queue.enqueue(msg.sender); - while (queue.checkPlace() > 1) { // wait until being the first buyer + while (queue.checkPlace(msg.sender) > 1) { // wait until being the first buyer continue; } - require(queue.checkPlace() == 1); + require(queue.checkPlace(msg.sender) == 1); while (queue.qsize() < 1) { // make sure the buyer always have ppl behind queue.checkTime(); - if (queue.checkPlace() == 0) { // times up + if (queue.checkPlace(msg.sender) == 0) { // times up //revert(); msg.sender.transfer(msg.value); TokenDelivered(msg.sender, false); @@ -98,7 +98,7 @@ contract Crowdsale { continue; } queue.checkTime(); - if (queue.checkPlace() == 0) { // times up + if (queue.checkPlace(msg.sender) == 0) { // times up //revert(); msg.sender.transfer(msg.value); TokenDelivered(msg.sender, false); diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 56b72a34..25dac4a1 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -47,9 +47,9 @@ contract Queue { * Returns the 1-indexed position of the sender in the line. * If person is not in line, returns 0. */ - function checkPlace() constant returns(uint8) { + function checkPlace(address add) constant returns(uint8) { for (uint8 i = 0; i < currentSize; i++) { - if(ParticipantsList[i].a == msg.sender) { + if(ParticipantsList[i].a == add) { return i; } } From 391ea5bccdb8d95a4916737d4a45663175540d97 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Sun, 29 Oct 2017 23:21:12 -0700 Subject: [PATCH 33/35] update testing --- test/TestQueue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TestQueue.js b/test/TestQueue.js index a05c5f84..df7f198b 100644 --- a/test/TestQueue.js +++ b/test/TestQueue.js @@ -39,7 +39,7 @@ contract('TestQueue', function(accounts){ await queue.enqueue(accounts[0]); await queue.enqueue(accounts[1]); await queue.enqueue(accounts[2]); - let position = await queue.checkPlace.call({from: accounts[1]}); + let position = await queue.checkPlace.call(accounts[1]); assert.equal(position, 1, "accounts[1] is at position 1"); }) }); From 98ffa8c1aa32e39efeaa04d6dae1064f706fc9e9 Mon Sep 17 00:00:00 2001 From: Jesse Paterson Date: Mon, 30 Oct 2017 00:11:30 -0700 Subject: [PATCH 34/35] Some last minute crowdsale edits --- contracts/Crowdsale.sol | 28 +++++++++++++++++++--------- contracts/Queue.sol | 2 +- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/contracts/Crowdsale.sol b/contracts/Crowdsale.sol index 914db019..a4cbaf82 100644 --- a/contracts/Crowdsale.sol +++ b/contracts/Crowdsale.sol @@ -6,8 +6,8 @@ import './utils/SafeMath.sol'; /** * @title Crowdsale - * @dev Contract that deploys `Token.sol` - * Is timelocked, manages buyer queue, updates balances on `Token.sol` + * @dev Contract that deploys Token.sol + * Is timelocked, manages buyer queue, updates balances on Token.sol */ contract Crowdsale { @@ -34,12 +34,13 @@ contract Crowdsale { } modifier saleHasNotEnded() { - require(startingTime < now && now < endingTime); + require(startingTime <= now && now <= endingTime); _; } + function Crowdsale( - uint256 _exhangeRate, + uint256 _exhangeRate, uint256 _totalSupply, uint _timeInMinutesForFundraising, uint _qtimelimit) @@ -51,15 +52,15 @@ contract Crowdsale { exchangeRate = _exhangeRate; token = new Token(_totalSupply); queue = new Queue(_qtimelimit); + totalRaised = 0; + currentBalence = 0; } - - function mint(uint256 amount) isCreator() { token.mint(amount); } - function burn(uint256 amount){ + function burn(uint256 amount) isCreator() { token.burn(amount); } @@ -82,10 +83,14 @@ contract Crowdsale { queue.enqueue(msg.sender); - while (queue.checkPlace() > 1) { // wait until being the first buyer + + while (queue.checkPlace() > 1 || queue.checkPlace() == 0) { // wait until being the first buyer continue; } + + require(queue.checkPlace() == 1); + return true; while (queue.qsize() < 1) { // make sure the buyer always have ppl behind queue.checkTime(); @@ -98,15 +103,20 @@ contract Crowdsale { continue; } queue.checkTime(); + + if (queue.checkPlace() == 0) { // times up //revert(); msg.sender.transfer(msg.value); TokenDelivered(msg.sender, false); return false; } + + queue.dequeue(); bool success = token.transfer(msg.sender, tokensAmount); if (success) { + totalRaised = SafeMath.add(totalRaised, weiToToken(msg.value)); currentBalence = SafeMath.add(currentBalence, msg.value); //currentBalence += msg.value; } @@ -116,7 +126,7 @@ contract Crowdsale { } - function refund(uint256 amount) saleHasNotEnded() returns (bool) { + function refund(uint256 amount) returns (bool) { bool good = token.refund(msg.sender, amount); if (good) { uint256 refundAmount = tokenToWei(amount); diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 56b72a34..54172d1a 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -81,7 +81,7 @@ contract Queue { /* Places `addr` in the first empty position in the queue */ function enqueue(address addr) { if(currentSize >= size){ - revert(); + //revert(); return; } ParticipantsList.push(Participant( addr, now )); From 8da556283401e499f4b97e5af25c82b454240f88 Mon Sep 17 00:00:00 2001 From: Andy Chen Date: Mon, 30 Oct 2017 17:09:11 -0700 Subject: [PATCH 35/35] update styles --- contracts/Queue.sol | 2 +- contracts/Token.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Queue.sol b/contracts/Queue.sol index 25dac4a1..2fa53220 100644 --- a/contracts/Queue.sol +++ b/contracts/Queue.sol @@ -37,7 +37,7 @@ contract Queue { /* Returns the address of the person in the front of the queue */ function getFirst() constant returns(address) { - if (currentSize > 0){ + if (currentSize > 0) { return ParticipantsList[0].a; } return address(0); diff --git a/contracts/Token.sol b/contracts/Token.sol index 8b9c0a24..0005fe9a 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -106,7 +106,7 @@ contract Token is ERC20Interface { /// @param _value The amount of tokens to be approved for transfer /// @return Whether the approval was successful or not function approve(address _spender, uint256 _value) public returns (bool success){ - allowed[msg.sender][_spender]+=_value; + allowed[msg.sender][_spender] += _value; Approval(msg.sender, _spender, _value); return true; }