diff --git a/contracts/HumanStandardToken.sol b/contracts/HumanStandardToken.sol index 63620e7..8ab7a2c 100644 --- a/contracts/HumanStandardToken.sol +++ b/contracts/HumanStandardToken.sol @@ -10,7 +10,7 @@ Machine-based, rapid creation of many tokens would not necessarily need these ex 3) Optional approveAndCall() functionality to notify a contract if an approval() has occurred. .*/ -pragma solidity ^0.4.4; +pragma solidity ^0.4.6; import "./StandardToken.sol"; diff --git a/contracts/HumanStandardTokenFactory.sol b/contracts/HumanStandardTokenFactory.sol new file mode 100644 index 0000000..e843060 --- /dev/null +++ b/contracts/HumanStandardTokenFactory.sol @@ -0,0 +1,62 @@ +import "./HumanStandardToken.sol"; + +pragma solidity ^0.4.6; + +contract HumanStandardTokenFactory { + + mapping(address => address[]) public created; + mapping(address => bool) public isHumanToken; //verify without having to do a bytecode check. + bytes public humanStandardByteCode; + + function HumanStandardTokenFactory() { + //upon creation of the factory, deploy a HumanStandardToken (parameters are meaningless) and store the bytecode provably. + address verifiedToken = createHumanStandardToken(10000, "Verify Token", 3, "VTX"); + humanStandardByteCode = codeAt(verifiedToken); + } + + //verifies if a contract that has been deployed is a Human Standard Token. + //NOTE: This is a very expensive function, and should only be used in an eth_call. ~800k gas + function verifyHumanStandardToken(address _tokenContract) returns (bool) { + bytes memory fetchedTokenByteCode = codeAt(_tokenContract); + + if (fetchedTokenByteCode.length != humanStandardByteCode.length) { + return false; //clear mismatch + } + + //starting iterating through it if lengths match + for (uint i = 0; i < fetchedTokenByteCode.length; i ++) { + if (fetchedTokenByteCode[i] != humanStandardByteCode[i]) { + return false; + } + } + + return true; + } + + //for now, keeping this internal. Ideally there should also be a live version of this that any contract can use, lib-style. + //retrieves the bytecode at a specific address. + function codeAt(address _addr) internal returns (bytes o_code) { + assembly { + // retrieve the size of the code, this needs assembly + let size := extcodesize(_addr) + // allocate output byte array - this could also be done without assembly + // by using o_code = new bytes(size) + o_code := mload(0x40) + // new "memory end" including padding + mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) + // store length in memory + mstore(o_code, size) + // actually retrieve the code, this needs assembly + extcodecopy(_addr, add(o_code, 0x20), 0, size) + } + } + + function createHumanStandardToken(uint256 _initialAmount, string _name, uint8 _decimals, string _symbol) returns (address) { + + HumanStandardToken newToken = (new HumanStandardToken(_initialAmount, _name, _decimals, _symbol)); + created[msg.sender].push(address(newToken)); + isHumanToken[address(newToken)] = true; + newToken.transfer(msg.sender, _initialAmount); //the factory will own the created tokens. You must transfer them. + return address(newToken); + } +} diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol new file mode 100644 index 0000000..1af4964 --- /dev/null +++ b/contracts/Migrations.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.6; + +contract Migrations { + address public owner; + uint public last_completed_migration; + + modifier restricted() { + if (msg.sender == owner) _; + } + + function Migrations() { + owner = msg.sender; + } + + function setCompleted(uint completed) restricted { + last_completed_migration = completed; + } + + function upgrade(address new_address) restricted { + Migrations upgraded = Migrations(new_address); + upgraded.setCompleted(last_completed_migration); + } +} diff --git a/contracts/StandardToken.sol b/contracts/StandardToken.sol index f82fdc3..c5dc557 100644 --- a/contracts/StandardToken.sol +++ b/contracts/StandardToken.sol @@ -7,7 +7,7 @@ If you deploy this, you won't have anything useful. Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20 .*/ -pragma solidity ^0.4.4; +pragma solidity ^0.4.6; import "./Token.sol"; diff --git a/contracts/Token.sol b/contracts/Token.sol index 2f40232..5530241 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.4; +pragma solidity ^0.4.6; contract Token { diff --git a/migrations/1_initial_migration.js b/migrations/1_initial_migration.js new file mode 100644 index 0000000..4d5f3f9 --- /dev/null +++ b/migrations/1_initial_migration.js @@ -0,0 +1,5 @@ +var Migrations = artifacts.require("./Migrations.sol"); + +module.exports = function(deployer) { + deployer.deploy(Migrations); +}; diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js new file mode 100644 index 0000000..7863361 --- /dev/null +++ b/migrations/2_deploy_contracts.js @@ -0,0 +1,5 @@ +var HumanStandardTokenFactory = artifacts.require("./HumanStandardTokenFactory.sol"); + +module.exports = function(deployer) { + deployer.deploy(HumanStandardTokenFactory); +};