diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build diff --git a/contracts/ERC20.sol b/contracts/ERC20.sol new file mode 100644 index 0000000..e2af082 --- /dev/null +++ b/contracts/ERC20.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.4.19; + +contract ERC20 { + function totalSupply() public constant returns (uint256 supply); + function balanceOf(address _owner) public view returns (uint256 balance); + function transfer(address _to, uint256 _value) public returns (bool success); + function transferFrom(address _from, address _to, uint256 _value) public returns (bool value); + function approve(address _sender, uint256 _value) public returns (bool success); + function allowance(address _owner, address _spender) public view returns (uint256 remaining); + + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _ownder, address indexed _spender, uint256 _value); +} diff --git a/contracts/ERC223.sol b/contracts/ERC223.sol new file mode 100644 index 0000000..bd1d9b9 --- /dev/null +++ b/contracts/ERC223.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.4.19; + +contract ERC223 { + function transfer(address _to, uint256 _value, bytes _data) public returns (bool success); + function transfer(address _to, uint256 _value, bytes _data, string _fallback) public returns (bool success); + event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes indexed _data); +} + diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol new file mode 100644 index 0000000..f170cb4 --- /dev/null +++ b/contracts/Migrations.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.17; + +contract Migrations { + address public owner; + uint public last_completed_migration; + + modifier restricted() { + if (msg.sender == owner) _; + } + + function Migrations() public { + owner = msg.sender; + } + + function setCompleted(uint completed) public restricted { + last_completed_migration = completed; + } + + function upgrade(address new_address) public restricted { + Migrations upgraded = Migrations(new_address); + upgraded.setCompleted(last_completed_migration); + } +} diff --git a/contracts/Zeny.sol b/contracts/Zeny.sol new file mode 100644 index 0000000..8892cb9 --- /dev/null +++ b/contracts/Zeny.sol @@ -0,0 +1,79 @@ +pragma solidity ^0.4.19; + +import "./ERC20.sol"; +import "./ERC223.sol"; +import "./ZenyReceivingContract.sol"; + +contract Zeny is ERC20, ERC223 { + uint256 constant private MAX_UINT256 = 2**256 - 1; + mapping (address => uint256) public balances; + mapping (address => mapping (address => uint256)) public allowed; + + string public name; + string public symbol; + uint8 public decimals; + uint256 internal supply; + + function Zeny( + uint256 _supply, + string _name, + string _symbol, + uint8 _decimals + ) public { + balances[msg.sender] = _supply; + supply = _supply; + name = _name; + symbol = _symbol; + decimals = _decimals; + } + + // Total number of tokens in existence. + function totalSupply() public constant returns (uint256) { + return supply; + } + + // Transfer token for a specified address. + function transfer(address _to, uint256 _value) public returns (bool success) { + require(_value <= balances[msg.sender]); + balances[msg.sender] -= _value; + balances[_to] += _value; + + Transfer(msg.sender, _to, _value); + return true; + } + + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { + require(_to != address(0)); + require(_value <= balances[_from]); + require(_value <= allowed[_from][msg.sender]); + + balances[_from] -= _value; + balances[_to] += _value; + + if (allowed[_from][msg.sender] < MAX_UINT256) { + allowed[_from][msg.sender] -= _value; + } + + Transfer(_from, _to, _value); + return true; + } + + // Gets the balance of the specified address. + function balanceOf(address _owner) public view returns (uint256 balance) { + return balances[_owner]; + } + + // Approve the passed address to spend the specified amount of tokens on behalf of + // msg.sender. + function approve(address _spender, uint256 _value) public returns (bool success) { + allowed[msg.sender][_spender] = _value; + + Approval(msg.sender, _spender, _value); + return true; + } + + // Check the amount of tokens that an owner allowed to a spender. + function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + return allowed[_owner][_spender]; + } +} diff --git a/contracts/ZenyFactory.sol b/contracts/ZenyFactory.sol new file mode 100644 index 0000000..163cb67 --- /dev/null +++ b/contracts/ZenyFactory.sol @@ -0,0 +1,58 @@ +pragma solidity ^0.4.19; + +import "./Zeny.sol"; + +contract ZenyFactory { + mapping (address => address[]) public created; + mapping (address => bool) public isZeny; + bytes public ZenyByteCode; + + function ZenyFactory() public { + address verifiedToken = createZeny(10000, "Zeny", 3, "ZNY"); + ZenyByteCode = codeAt(verifiedToken); + } + + function verifyZeny(address _tokenContract) public view returns (bool) { + bytes memory fetchedTokenByteCode = codeAt(_tokenContract); + if (fetchedTokenByteCode.length != ZenyByteCode.length) { + return false; + } + + for (uint i = 0; i < fetchedTokenByteCode.length; i++) { + if (fetchedTokenByteCode[i] != ZenyByteCode[i]) { + return false; + } + } + + return true; + } + + function createZeny(uint256 _initialAmount, string _name, uint8 _decimals, string _symbol) public returns (address) { + Zeny newToken = (new Zeny(_initialAmount, _name, _symbol, _decimals)); + created[msg.sender].push(address(newToken)); + isZeny[address(newToken)] = true; + newToken.transfer(msg.sender, _initialAmount); + return address(newToken); + } + + // Retrieves the bytecode at a specific address. + function codeAt(address _addr) internal view returns (bytes outputCode) { + assembly { + // Retrieve the size of the code. + let size := extcodesize(_addr) + + // Allocate output byte array. + outputCode := mload(0x40) + + // New memory end includes padding. + mstore(0x40, add(outputCode, and(add(add(size, 0x20), 0x1f), not(0x1f)))) + + // Store length in memory. + mstore(outputCode, size) + + // Retrieve the code. + extcodecopy(_addr, add(outputCode, 0x20), 0, size) + } + } +} + diff --git a/contracts/ZenyReceivingContract.sol b/contracts/ZenyReceivingContract.sol new file mode 100644 index 0000000..469599b --- /dev/null +++ b/contracts/ZenyReceivingContract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.4.19; + +contract ZenyReceivingContract { + function tokenFallback(address _from, uint _value, bytes _data) public; +} 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/truffle-config.js b/truffle-config.js new file mode 100644 index 0000000..a6330d6 --- /dev/null +++ b/truffle-config.js @@ -0,0 +1,4 @@ +module.exports = { + // See + // to customize your Truffle configuration! +}; diff --git a/truffle.js b/truffle.js new file mode 100644 index 0000000..a6330d6 --- /dev/null +++ b/truffle.js @@ -0,0 +1,4 @@ +module.exports = { + // See + // to customize your Truffle configuration! +};