-
Notifications
You must be signed in to change notification settings - Fork 19
/
EIP20Factory.sol
66 lines (55 loc) · 2.64 KB
/
EIP20Factory.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import "./EIP20.sol";
pragma solidity ^0.4.21;
contract EIP20Factory {
mapping(address => address[]) public created;
mapping(address => bool) public isEIP20; //verify without having to do a bytecode check.
bytes public EIP20ByteCode; // solhint-disable-line var-name-mixedcase
constructor() public {
//upon creation of the factory, deploy a EIP20 (parameters are meaningless) and store the bytecode provably.
address verifiedToken = createEIP20(10000, "Verify Token", 3, "VTX");
EIP20ByteCode = 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 verifyEIP20(address _tokenContract) public view returns (bool) {
bytes memory fetchedTokenByteCode = codeAt(_tokenContract);
if (fetchedTokenByteCode.length != EIP20ByteCode.length) {
return false; //clear mismatch
}
//starting iterating through it if lengths match
for (uint i = 0; i < fetchedTokenByteCode.length; i++) {
if (fetchedTokenByteCode[i] != EIP20ByteCode[i]) {
return false;
}
}
return true;
}
function createEIP20(uint256 _initialAmount, string _name, uint8 _decimals, string _symbol)
public
returns (address) {
EIP20 newToken = (new EIP20(_initialAmount, _name, _decimals, _symbol));
created[msg.sender].push(address(newToken));
isEIP20[address(newToken)] = true;
//the factory will own the created tokens. You must transfer them.
newToken.transfer(msg.sender, _initialAmount);
return address(newToken);
}
//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 view returns (bytes outputCode) {
assembly { // solhint-disable-line no-inline-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 outputCode = new bytes(size)
outputCode := mload(0x40)
// new "memory end" including padding
mstore(0x40, add(outputCode, and(add(add(size, 0x20), 0x1f), not(0x1f))))
// store length in memory
mstore(outputCode, size)
// actually retrieve the code, this needs assembly
extcodecopy(_addr, add(outputCode, 0x20), 0, size)
}
}
}