Ver código fonte

Several changes.
- Made StandardToken.sol ONLY implement ERC20 and nothing else.
- Added in HumanStandardToken.sol with optional extra for human deployment (finite supply, approveAndCall, vanity vars)
- New tests

Simon de la Rouviere 8 anos atrás
pai
commit
5252384b9a

+ 10 - 3
README.md

@@ -1,10 +1,17 @@
 # Tokens
 
-Contains Solidity smart contract code to issue a simple token on Ethereum. It can be used to create any form of asset, currency, coin, hours, usage tokens, vunk, etc.  
+This repo contains Solidity smart contract code to issue simple, standards-compliant tokens on Ethereum. It can be used to create any form of asset, currency, coin, hours, usage tokens, vunk, etc.  
 
-It based on the idea that creator of the token contract issues the initial & total supply. This is a Truffle repo that contains the code as well as a suite of tests.  
+The default is StandardToken.sol which ONLY implements the core ERC20 standard functionality (https://github.com/ethereum/EIPs/issues/20).  
+HumanStandardToken.sol is an example of a token that has optional extras fit for your issuing your own tokens, to be mainly used by other humans. It includes:  
 
-It follows the cutting edge standards (which is de facto finalised by the community here: https://github.com/ethereum/EIPs/issues/20). Following this standard allows other contract developers to easily incorporate your token into their application (governance, exchanges, games, etc). It will be updated as often as possible.  
+1) Initial Finite Supply (upon creation one specifies how much is minted).  
+2) In the absence of a token registry: Optional Decimal, Symbol & Name.  
+3) Optional approveAndCall() functionality to notify a contract if an approval() has occurred.  
+
+There is a set of tests written for the HumanStandardToken.sol using the Truffle framework to do so.
+
+Standards allows other contract developers to easily incorporate your token into their application (governance, exchanges, games, etc). It will be updated as often as possible.  
 
 Pull requests are welcome! Please keep standards discussions to the EIP repos.
 

+ 58 - 0
Token_Contracts/contracts/HumanStandardToken.sol

@@ -0,0 +1,58 @@
+/*
+This Token Contract implements the standard token functionality (https://github.com/ethereum/EIPs/issues/20) as well as the following OPTIONAL extras intended for use by humans.
+
+In other words. This is intended for deployment in something like a Token Factory or Mist wallet, and then used by humans.
+Imagine coins, currencies, shares, voting weight, etc.
+Machine-based, rapid creation of many tokens would not necessarily need these extra features or will be minted in other manners.
+
+1) Initial Finite Supply (upon creation one specifies how much is minted).
+2) In the absence of a token registry: Optional Decimal, Symbol & Name.
+3) Optional approveAndCall() functionality to notify a contract if an approval() has occurred.
+
+.*/
+
+import "StandardToken.sol";
+
+contract HumanStandardToken is StandardToken {
+
+    function () {
+        //if ether is sent to this address, send it back.
+        throw;
+    }
+
+    /* Public variables of the token */
+
+    /*
+    NOTE:
+    The following variables are OPTIONAL vanities. One does not have to include them.
+    They allow one to customise the token contract & in no way influences the core functionality.
+    Some wallets/interfaces might not even bother to look at this information.
+    */
+    string public name;                   //fancy name: eg Simon Bucks
+    uint8 public decimals;                //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether.
+    string public symbol;                 //An identifier: eg SBX
+    string public version = 'H0.1';       //human 0.1 standard. Just an arbitrary versioning scheme.
+
+    function HumanStandardToken(
+        uint256 _initialAmount,
+        string _tokenName,
+        uint8 _decimalUnits,
+        string _tokenSymbol
+        ) {
+        balances[msg.sender] = _initialAmount;               // Give the creator all initial tokens
+        totalSupply = _initialAmount;                        // Update total supply
+        name = _tokenName;                                   // Set the name for display purposes
+        decimals = _decimalUnits;                            // Amount of decimals for display purposes
+        symbol = _tokenSymbol;                               // Set the symbol for display purposes
+    }
+
+    /* Approves and then calls the receiving contract */
+    function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
+        allowed[msg.sender][_spender] = _value;
+        //call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.
+        //receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)
+        _spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData);
+        Approval(msg.sender, _spender, _value);
+        return true;
+    }
+}

+ 19 - 0
Token_Contracts/contracts/HumanStandardTokenFactory.sol

@@ -0,0 +1,19 @@
+import "HumanStandardToken.sol";
+
+contract HumanStandardTokenFactory {
+
+    mapping(address => address[]) public created;
+
+    function createdByMe() returns (address[]) {
+        return created[msg.sender];
+    }
+
+    function createHumanStandardToken(uint256 _initialAmount, string _name, uint8 _decimals, string _symbol) returns (address) {
+
+        address newTokenAddr = address(new HumanStandardToken(_initialAmount, _name, _decimals, _symbol));
+        HumanStandardToken newToken = HumanStandardToken(newTokenAddr);
+        newToken.transfer(msg.sender, _initialAmount); //the factory will own the created tokens. You must transfer them.
+        created[msg.sender].push(newTokenAddr);
+        return newTokenAddr;
+    }
+}

+ 20 - 0
Token_Contracts/contracts/SampleRecipient.sol

@@ -0,0 +1,20 @@
+/*
+This is an example contract that helps test the functionality of the approveAndCall() functionality of HumanStandardToken.sol.
+*/
+contract SampleRecipient {
+  /* A Generic receiving function for contracts that accept tokens */
+  address public from;
+  uint256 public value;
+  address public tokenContract;
+  bytes public extraData;
+
+  event ReceivedApproval(uint256 _value);
+
+  function receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData) {
+    from = _from;
+    value = _value;
+    tokenContract = _tokenContract;
+    extraData = _extraData;
+    ReceivedApproval(_value);
+  }
+}

+ 56 - 0
Token_Contracts/contracts/StandardToken.sol

@@ -0,0 +1,56 @@
+/*
+This implements ONLY the standard functions and NOTHING else.
+For a token like you would want to deploy in something like Mist, see HumanStandardToken.sol.
+
+If you deploy this, you won't have anything useful.
+
+Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20
+.*/
+
+import "Token.sol";
+
+contract StandardToken is Token {
+
+    function transfer(address _to, uint256 _value) returns (bool success) {
+        //Default assumes totalSupply can't be over max (2^256 - 1).
+        //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
+        //Replace the if with this one instead.
+        //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
+        if (balances[msg.sender] >= _value && _value > 0) {
+            balances[msg.sender] -= _value;
+            balances[_to] += _value;
+            Transfer(msg.sender, _to, _value);
+            return true;
+        } else { return false; }
+    }
+
+    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
+        //same as above. Replace this line with the following if you want to protect against wrapping uints.
+        //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
+        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
+            balances[_to] += _value;
+            balances[_from] -= _value;
+            allowed[_from][msg.sender] -= _value;
+            Transfer(_from, _to, _value);
+            return true;
+        } else { return false; }
+    }
+
+    function balanceOf(address _owner) constant returns (uint256 balance) {
+        return balances[_owner];
+    }
+
+    function approve(address _spender, uint256 _value) returns (bool success) {
+        allowed[msg.sender][_spender] = _value;
+        Approval(msg.sender, _spender, _value);
+        return true;
+    }
+
+    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
+      return allowed[_owner][_spender];
+    }
+
+    mapping (address => uint256) balances;
+    mapping (address => mapping (address => uint256)) allowed;
+    uint256 public totalSupply;
+}

+ 8 - 68
Token_Contracts/contracts/Standard_Token.sol

@@ -1,69 +1,9 @@
-/*Most, basic default, standardised Token contract.
-Allows the creation of a token with a finite issued amount to the creator.
-
-Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20
-.*/
-
-import "Token.sol";
-
-contract Standard_Token is Token {
-
-    function Standard_Token(uint256 _initialAmount) {
-        balances[msg.sender] = _initialAmount;
-        totalSupply = _initialAmount;
-    }
-
-    function () {
-        //if ether is sent to this address, send it back.
-        throw;
-    }
-
-    function transfer(address _to, uint256 _value) returns (bool success) {
-        //Default assumes totalSupply can't be over max (2^256 - 1).
-        //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
-        //Replace the if with this one instead.
-        //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
-        if (balances[msg.sender] >= _value && _value > 0) {
-            balances[msg.sender] -= _value;
-            balances[_to] += _value;
-            Transfer(msg.sender, _to, _value);
-            return true;
-        } else { return false; }
-    }
-
-    //NOTE: This function will throw errors wrt changing storage where it should not, due to the optimizer errors, IF not careful.
-    //As it is now, it works for both earlier and newer solc versions. (NO need to change anything)
-    //In the future, the TransferFrom event will be moved to just before "return true;" in order to make it more elegant (once the new solc version is out of develop).
-    //If you want to move parts of this function around and it breaks, you'll need at least:
-    //Over commit: https://github.com/ethereum/solidity/commit/67c855c583042ddee6261a9921239a3afd086c14 (last successfully working commit)
-    //See issue for details: https://github.com/ethereum/solidity/issues/333 & issue: https://github.com/ethereum/solidity/issues/281
-    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
-        //same as above. Replace this line with the following if you want to protect against wrapping uints.
-        //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
-        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
-            balances[_to] += _value;
-            Transfer(_from, _to, _value);
-            balances[_from] -= _value;
-            allowed[_from][msg.sender] -= _value;
-            return true;
-        } else { return false; }
-    }
-
-    function balanceOf(address _owner) constant returns (uint256 balance) {
-        return balances[_owner];
-    }
-
-    function approve(address _spender, uint256 _value) returns (bool success) {
-        allowed[msg.sender][_spender] = _value;
-        Approval(msg.sender, _spender, _value);
-        return true;
-    }
-
-    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
-      return allowed[_owner][_spender];
-    }
-
-    mapping (address => uint256) balances;
-    mapping (address => mapping (address => uint256)) allowed;
-    uint256 public totalSupply;
+/*
+This has moved/changed to StandardToken.sol to conform to the Solidity naming standards.
+For a contract that ONLY implements the standard functions, see StandardToken.sol.
+For a contract to deploy in Mist with optional extra, see HumanStandardToken.sol.
+*/
+
+contract Standard_Token {
+  //this is just here to satisfy Truffle's complaining
 }

+ 0 - 19
Token_Contracts/contracts/Standard_Token_Factory.sol

@@ -1,19 +0,0 @@
-import "Standard_Token.sol";
-
-contract Standard_Token_Factory {
-
-    mapping(address => address[]) public created;
-
-    function createdByMe() returns (address[]) {
-        return created[msg.sender];
-    }
-
-    function createStandardToken(uint256 _initialAmount) returns (address) {
-
-        address newTokenAddr = address(new Standard_Token(_initialAmount));
-        Standard_Token newToken = Standard_Token(newTokenAddr);
-        newToken.transfer(msg.sender, _initialAmount); //the factory will own the created tokens. You must transfer them.
-        created[msg.sender].push(newTokenAddr);
-        return newTokenAddr;
-    }
-}

+ 4 - 4
Token_Contracts/contracts/TokenTester.sol

@@ -1,12 +1,12 @@
-import "Standard_Token_Factory.sol";
+import "HumanStandardTokenFactory.sol";
 
 contract TokenTester {
     address public tokenContractAddress;
 
     function TokenTester() {
-        address factoryAddr = address(new Standard_Token_Factory());
-        Standard_Token_Factory tokenFactory = Standard_Token_Factory(factoryAddr);
+        address factoryAddr = address(new HumanStandardTokenFactory());
+        HumanStandardTokenFactory tokenFactory = HumanStandardTokenFactory(factoryAddr);
 
-        tokenContractAddress = tokenFactory.createStandardToken(10000);
+        tokenContractAddress = tokenFactory.createHumanStandardToken(10000, 'Simon Bucks', 1, 'SBX');
     }
 }

Diferenças do arquivo suprimidas por serem muito extensas
+ 65 - 0
Token_Contracts/environments/test/contracts/HumanStandardToken.sol.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 65 - 0
Token_Contracts/environments/test/contracts/HumanStandardTokenFactory.sol.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 65 - 0
Token_Contracts/environments/test/contracts/SampleRecipient.sol.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 65 - 0
Token_Contracts/environments/test/contracts/StandardToken.sol.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 49 - 45
Token_Contracts/environments/test/contracts/Standard_Token.sol.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 61
Token_Contracts/environments/test/contracts/Standard_Token_Factory.sol.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 49 - 45
Token_Contracts/environments/test/contracts/Token.sol.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 49 - 45
Token_Contracts/environments/test/contracts/TokenTester.sol.js


+ 282 - 0
Token_Contracts/test/humanStandardToken.js

@@ -0,0 +1,282 @@
+contract("HumanStandardToken", function(accounts) {
+
+/*TODO:
+Test approveAndCall.
+*/
+
+/*CREATION*/
+
+    it("creation: should create an initial balance of 10000 for the creator", function(done) {
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(ctr) {
+            return ctr.balanceOf.call(accounts[0]);
+    }).then(function (result) {
+        assert.strictEqual(result.c[0], 10000);
+        done();
+        }).catch(done);
+    });
+
+    it("creation: test correct setting of vanity information", function(done) {
+      var ctr;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.name.call();
+    }).then(function (result) {
+        assert.strictEqual(result, 'Simon Bucks');
+        return ctr.decimals.call();
+    }).then(function(result) {
+        assert.strictEqual(result.c[0], 1);
+        return ctr.symbol.call();
+    }).then(function(result) {
+        assert.strictEqual(result, 'SBX');
+        done();
+        }).catch(done);
+    });
+
+    it("creation: should succeed in creating over 2^256 - 1 (max) tokens", function(done) {
+        //2^256 - 1
+        HumanStandardToken.new('115792089237316195423570985008687907853269984665640564039457584007913129639935', 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(ctr) {
+            return ctr.totalSupply();
+    }).then(function (result) {
+        var match = result.equals('1.15792089237316195423570985008687907853269984665640564039457584007913129639935e+77');
+        assert.isTrue(match);
+        done();
+        }).catch(done);
+    });
+
+/*TRANSERS*/
+//normal transfers without approvals.
+
+    //this is not *good* enough as the contract could still throw an error otherwise.
+    //ideally one should check balances before and after, but estimateGas currently always throws an error.
+    //it's not giving estimate on gas used in the event of an error.
+    it("transfers: ether transfer should be reversed.", function(done) {
+        var ctr;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return web3.eth.sendTransaction({from: accounts[0], to: ctr.address, value: web3.toWei("10", "Ether")});
+        }).catch(function(result) {
+            done();
+        }).catch(done);
+    });
+
+
+    it("transfers: should transfer 10000 to accounts[1] with accounts[0] having 10000", function(done) {
+        var ctr;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.transfer(accounts[1], 10000, {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.balanceOf.call(accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 10000);
+            done();
+        }).catch(done);
+    });
+
+    it("transfers: should fail when trying to transfer 10001 to accounts[1] with accounts[0] having 10000", function(done) {
+        var ctr;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.transfer.call(accounts[1], 10001, {from: accounts[0]});
+        }).then(function (result) {
+            assert.isFalse(result);
+            done();
+        }).catch(done);
+    });
+
+    it("transfers: should fail when trying to transfer zero.", function(done) {
+        var ctr;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.transfer.call(accounts[1], 0, {from: accounts[0]});
+        }).then(function (result) {
+            assert.isFalse(result);
+            done();
+        }).catch(done);
+    });
+
+    //NOTE: testing uint256 wrapping is impossible in this standard token since you can't supply > 2^256 -1.
+
+    //todo: transfer max amounts.
+
+/*APPROVALS*/
+
+    it("approvals: msg.sender should approve 100 to accounts[1]", function(done) {
+        var ctr = null;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.approve(accounts[1], 100, {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.allowance.call(accounts[0], accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 100);
+            done();
+        }).catch(done);
+    });
+
+    it("approvals: msg.sender should approve 100 to SampleRecipient and then NOTIFY SampleRecipient", function(done) {
+        var ctr = null;
+        var sampleCtr = null
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return SampleRecipient.new({from: accounts[0]});
+        }).then(function(result) {
+            sampleCtr = result;
+            return ctr.approveAndCall(sampleCtr.address, 100, '0x42', {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.allowance.call(accounts[0], sampleCtr.address);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 100);
+            return sampleCtr.value.call();
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 100);
+            done();
+        }).catch(done);
+    });
+
+    //bit overkill. But is for testing a bug
+    it("approvals: msg.sender approves accounts[1] of 100 & withdraws 20 once.", function(done) {
+        var ctr = null;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.balanceOf.call(accounts[0]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 10000);
+            return ctr.approve(accounts[1], 100, {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.balanceOf.call(accounts[2]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 0);
+            return ctr.allowance.call(accounts[0], accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 100);
+            return ctr.transferFrom.call(accounts[0], accounts[2], 20, {from: accounts[1]});
+        }).then(function (result) {
+            return ctr.transferFrom(accounts[0], accounts[2], 20, {from: accounts[1]});
+        }).then(function (result) {
+            return ctr.allowance.call(accounts[0], accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 80);
+            return ctr.balanceOf.call(accounts[2]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 20);
+            return ctr.balanceOf.call(accounts[0]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 9980);
+            done();
+        }).catch(done);
+    });
+
+    //should approve 100 of msg.sender & withdraw 50, twice. (should succeed)
+    it("approvals: msg.sender approves accounts[1] of 100 & withdraws 20 twice.", function(done) {
+        var ctr = null;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.approve(accounts[1], 100, {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.allowance.call(accounts[0], accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 100);
+            return ctr.transferFrom(accounts[0], accounts[2], 20, {from: accounts[1]});
+        }).then(function (result) {
+            return ctr.allowance.call(accounts[0], accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 80);
+            return ctr.balanceOf.call(accounts[2]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 20);
+            return ctr.balanceOf.call(accounts[0]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 9980);
+            //FIRST tx done.
+            //onto next.
+            return ctr.transferFrom(accounts[0], accounts[2], 20, {from: accounts[1]});
+        }).then(function (result) {
+            return ctr.allowance.call(accounts[0], accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 60);
+            return ctr.balanceOf.call(accounts[2]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 40);
+            return ctr.balanceOf.call(accounts[0]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 9960);
+            done();
+        }).catch(done);
+    });
+
+    //should approve 100 of msg.sender & withdraw 50 & 60 (should fail).
+    it("approvals: msg.sender approves accounts[1] of 100 & withdraws 50 & 60 (2nd tx should fail)", function(done) {
+        var ctr = null;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.approve(accounts[1], 100, {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.allowance.call(accounts[0], accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 100);
+            return ctr.transferFrom(accounts[0], accounts[2], 50, {from: accounts[1]});
+        }).then(function (result) {
+            return ctr.allowance.call(accounts[0], accounts[1]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 50);
+            return ctr.balanceOf.call(accounts[2]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 50);
+            return ctr.balanceOf.call(accounts[0]);
+        }).then(function (result) {
+            assert.strictEqual(result.c[0], 9950);
+            //FIRST tx done.
+            //onto next.
+            return ctr.transferFrom.call(accounts[0], accounts[2], 60, {from: accounts[1]});
+        }).then(function (result) {
+            assert.isFalse(result);
+            done();
+        }).catch(done);
+    });
+
+    it("approvals: attempt withdrawal from acconut with no allowance (should fail)", function(done) {
+        var ctr = null;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.transferFrom.call(accounts[0], accounts[2], 60, {from: accounts[1]});
+        }).then(function (result) {
+              assert.isFalse(result);
+              done();
+        }).catch(done);
+    });
+
+    it("approvals: allow accounts[1] 100 to withdraw from accounts[0]. Withdraw 60 and then approve 0 & attempt transfer.", function(done) {
+        var ctr = null;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.approve(accounts[1], 100, {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.transferFrom(accounts[0], accounts[2], 60, {from: accounts[1]});
+        }).then(function (result) {
+            return ctr.approve(accounts[1], 0, {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.transferFrom.call(accounts[0], accounts[2], 10, {from: accounts[1]});
+        }).then(function (result) {
+              assert.isFalse(result);
+              done();
+        }).catch(done);
+    });
+
+    it("approvals: approve max (2^256 - 1)", function(done) {
+        var ctr = null;
+        HumanStandardToken.new(10000, 'Simon Bucks', 1, 'SBX', {from: accounts[0]}).then(function(result) {
+            ctr = result;
+            return ctr.approve(accounts[1],'115792089237316195423570985008687907853269984665640564039457584007913129639935' , {from: accounts[0]});
+        }).then(function (result) {
+            return ctr.allowance(accounts[0], accounts[1]);
+        }).then(function (result) {
+            var match = result.equals('1.15792089237316195423570985008687907853269984665640564039457584007913129639935e+77');
+            assert.isTrue(match);
+            done();
+        }).catch(done);
+    });
+
+    //todo, max approvals.
+
+});

+ 1 - 241
Token_Contracts/test/standardToken.js

@@ -1,241 +1 @@
-contract("Standard_Token", function(accounts) {
-
-/*CREATION*/
-
-    it("creation: should create an initial balance of 10000 for the creator", function(done) {
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(ctr) {
-            return ctr.balanceOf.call(accounts[0]);
-    }).then(function (result) {
-        assert.strictEqual(result.c[0], 10000);
-        done();
-        }).catch(done);
-    });
-
-    it("creation: should succeed in creating over 2^256 - 1 (max) tokens", function(done) {
-        //2^256 - 1
-        Standard_Token.new('115792089237316195423570985008687907853269984665640564039457584007913129639935', {from: accounts[0]}).then(function(ctr) {
-            return ctr.totalSupply();
-    }).then(function (result) {
-        var match = result.equals('1.15792089237316195423570985008687907853269984665640564039457584007913129639935e+77');
-        assert.isTrue(match);
-        done();
-        }).catch(done);
-    });
-
-/*TRANSERS*/
-//normal transfers without approvals.
-
-    //this is not *good* enough as the contract could still throw an error otherwise.
-    //ideally one should check balances before and after, but estimateGas currently always throws an error.
-    //it's not giving estimate on gas used in the event of an error.
-    it("transfers: ether transfer should be reversed.", function(done) {
-        var ctr;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return web3.eth.sendTransaction({from: accounts[0], to: ctr.address, value: web3.toWei("10", "Ether")});
-        }).catch(function(result) {
-            done();
-        }).catch(done);
-    });
-
-
-    it("transfers: should transfer 10000 to accounts[1] with accounts[0] having 10000", function(done) {
-        var ctr;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.transfer(accounts[1], 10000, {from: accounts[0]});
-        }).then(function (result) {
-            return ctr.balanceOf.call(accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 10000);
-            done();
-        }).catch(done);
-    });
-
-    it("transfers: should fail when trying to transfer 10001 to accounts[1] with accounts[0] having 10000", function(done) {
-        var ctr;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.transfer.call(accounts[1], 10001, {from: accounts[0]});
-        }).then(function (result) {
-            assert.isFalse(result);
-            done();
-        }).catch(done);
-    });
-
-    it("transfers: should fail when trying to transfer zero.", function(done) {
-        var ctr;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.transfer.call(accounts[1], 0, {from: accounts[0]});
-        }).then(function (result) {
-            assert.isFalse(result);
-            done();
-        }).catch(done);
-    });
-
-    //NOTE: testing uint256 wrapping is impossible in this standard token since you can't supply > 2^256 -1.
-
-    //todo: transfer max amounts.
-
-/*APPROVALS*/
-
-    it("approvals: msg.sender should approve 100 to accounts[1]", function(done) {
-        var ctr = null;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.approve(accounts[1], 100, {from: accounts[0]});
-        }).then(function (result) {
-            return ctr.allowance.call(accounts[0], accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 100);
-            done();
-        }).catch(done);
-    });
-
-    //bit overkill. But is for testing a bug
-    it("approvals: msg.sender approves accounts[1] of 100 & withdraws 20 once.", function(done) {
-        var ctr = null;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.balanceOf.call(accounts[0]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 10000);
-            return ctr.approve(accounts[1], 100, {from: accounts[0]});
-        }).then(function (result) {
-            return ctr.balanceOf.call(accounts[2]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 0);
-            return ctr.allowance.call(accounts[0], accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 100);
-            return ctr.transferFrom.call(accounts[0], accounts[2], 20, {from: accounts[1]});
-        }).then(function (result) {
-            return ctr.transferFrom(accounts[0], accounts[2], 20, {from: accounts[1]});
-        }).then(function (result) {
-            return ctr.allowance.call(accounts[0], accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 80);
-            return ctr.balanceOf.call(accounts[2]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 20);
-            return ctr.balanceOf.call(accounts[0]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 9980);
-            done();
-        }).catch(done);
-    });
-
-    //should approve 100 of msg.sender & withdraw 50, twice. (should succeed)
-    it("approvals: msg.sender approves accounts[1] of 100 & withdraws 20 twice.", function(done) {
-        var ctr = null;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.approve(accounts[1], 100, {from: accounts[0]});
-        }).then(function (result) {
-            return ctr.allowance.call(accounts[0], accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 100);
-            return ctr.transferFrom(accounts[0], accounts[2], 20, {from: accounts[1]});
-        }).then(function (result) {
-            return ctr.allowance.call(accounts[0], accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 80);
-            return ctr.balanceOf.call(accounts[2]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 20);
-            return ctr.balanceOf.call(accounts[0]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 9980);
-            //FIRST tx done.
-            //onto next.
-            return ctr.transferFrom(accounts[0], accounts[2], 20, {from: accounts[1]});
-        }).then(function (result) {
-            return ctr.allowance.call(accounts[0], accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 60);
-            return ctr.balanceOf.call(accounts[2]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 40);
-            return ctr.balanceOf.call(accounts[0]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 9960);
-            done();
-        }).catch(done);
-    });
-
-    //should approve 100 of msg.sender & withdraw 50 & 60 (should fail).
-    it("approvals: msg.sender approves accounts[1] of 100 & withdraws 50 & 60 (2nd tx should fail)", function(done) {
-        var ctr = null;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.approve(accounts[1], 100, {from: accounts[0]});
-        }).then(function (result) {
-            return ctr.allowance.call(accounts[0], accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 100);
-            return ctr.transferFrom(accounts[0], accounts[2], 50, {from: accounts[1]});
-        }).then(function (result) {
-            return ctr.allowance.call(accounts[0], accounts[1]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 50);
-            return ctr.balanceOf.call(accounts[2]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 50);
-            return ctr.balanceOf.call(accounts[0]);
-        }).then(function (result) {
-            assert.strictEqual(result.c[0], 9950);
-            //FIRST tx done.
-            //onto next.
-            return ctr.transferFrom.call(accounts[0], accounts[2], 60, {from: accounts[1]});
-        }).then(function (result) {
-            assert.isFalse(result);
-            done();
-        }).catch(done);
-    });
-
-    it("approvals: attempt withdrawal from acconut with no allowance (should fail)", function(done) {
-        var ctr = null;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.transferFrom.call(accounts[0], accounts[2], 60, {from: accounts[1]});
-        }).then(function (result) {
-              assert.isFalse(result);
-              done();
-        }).catch(done);
-    });
-
-    it("approvals: allow accounts[1] 100 to withdraw from accounts[0]. Withdraw 60 and then approve 0 & attempt transfer.", function(done) {
-        var ctr = null;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.approve(accounts[1], 100, {from: accounts[0]});
-        }).then(function (result) {
-            return ctr.transferFrom(accounts[0], accounts[2], 60, {from: accounts[1]});
-        }).then(function (result) {
-            return ctr.approve(accounts[1], 0, {from: accounts[0]});
-        }).then(function (result) {
-            return ctr.transferFrom.call(accounts[0], accounts[2], 10, {from: accounts[1]});
-        }).then(function (result) {
-              assert.isFalse(result);
-              done();
-        }).catch(done);
-    });
-
-    it("approvals: approve max (2^256 - 1)", function(done) {
-        var ctr = null;
-        Standard_Token.new(10000, {from: accounts[0]}).then(function(result) {
-            ctr = result;
-            return ctr.approve(accounts[1],'115792089237316195423570985008687907853269984665640564039457584007913129639935' , {from: accounts[0]});
-        }).then(function (result) {
-            return ctr.allowance(accounts[0], accounts[1]);
-        }).then(function (result) {
-            var match = result.equals('1.15792089237316195423570985008687907853269984665640564039457584007913129639935e+77');
-            assert.isTrue(match);
-            done();
-        }).catch(done);
-    });
-
-    //todo, max approvals.
-
-});
+/* This has moved to humandStandardToken.js */

+ 1 - 1
Token_Contracts/test/tokenTester.js

@@ -3,7 +3,7 @@ contract("TokenTester", function(accounts) {
         var tester = TokenTester.at(TokenTester.deployed_address);
         tester.tokenContractAddress.call()
         .then(function(tokenContractAddr) {
-            var tokenContract = Standard_Token.at(tokenContractAddr);
+            var tokenContract = HumanStandardToken.at(tokenContractAddr);
             return tokenContract.balanceOf.call(TokenTester.deployed_address);
         }).then(function (result) {
             assert.strictEqual(result.c[0], 10000);  // 10000 as specified in TokenTester.sol