EIP20Factory.sol 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import "./EIP20.sol";
  2. pragma solidity ^0.4.18;
  3. contract EIP20Factory {
  4. mapping(address => address[]) public created;
  5. mapping(address => bool) public isEIP20; //verify without having to do a bytecode check.
  6. bytes public EIP20ByteCode; // solhint-disable-line var-name-mixedcase
  7. function EIP20Factory() public {
  8. //upon creation of the factory, deploy a EIP20 (parameters are meaningless) and store the bytecode provably.
  9. address verifiedToken = createEIP20(10000, "Verify Token", 3, "VTX");
  10. EIP20ByteCode = codeAt(verifiedToken);
  11. }
  12. //verifies if a contract that has been deployed is a Human Standard Token.
  13. //NOTE: This is a very expensive function, and should only be used in an eth_call. ~800k gas
  14. function verifyEIP20(address _tokenContract) public view returns (bool) {
  15. bytes memory fetchedTokenByteCode = codeAt(_tokenContract);
  16. if (fetchedTokenByteCode.length != EIP20ByteCode.length) {
  17. return false; //clear mismatch
  18. }
  19. //starting iterating through it if lengths match
  20. for (uint i = 0; i < fetchedTokenByteCode.length; i++) {
  21. if (fetchedTokenByteCode[i] != EIP20ByteCode[i]) {
  22. return false;
  23. }
  24. return true;
  25. }
  26. }
  27. function createEIP20(uint256 _initialAmount, string _name, uint8 _decimals, string _symbol)
  28. public
  29. returns (address) {
  30. EIP20 newToken = (new EIP20(_initialAmount, _name, _decimals, _symbol));
  31. created[msg.sender].push(address(newToken));
  32. isEIP20[address(newToken)] = true;
  33. //the factory will own the created tokens. You must transfer them.
  34. newToken.transfer(msg.sender, _initialAmount);
  35. return address(newToken);
  36. }
  37. //for now, keeping this internal. Ideally there should also be a live version of this that
  38. // any contract can use, lib-style.
  39. //retrieves the bytecode at a specific address.
  40. function codeAt(address _addr) internal view returns (bytes outputCode) {
  41. assembly { // solhint-disable-line no-inline-assembly
  42. // retrieve the size of the code, this needs assembly
  43. let size := extcodesize(_addr)
  44. // allocate output byte array - this could also be done without assembly
  45. // by using outputCode = new bytes(size)
  46. outputCode := mload(0x40)
  47. // new "memory end" including padding
  48. mstore(0x40, add(outputCode, and(add(add(size, 0x20), 0x1f), not(0x1f))))
  49. // store length in memory
  50. mstore(outputCode, size)
  51. // actually retrieve the code, this needs assembly
  52. extcodecopy(_addr, add(outputCode, 0x20), 0, size)
  53. }
  54. }
  55. }