最近要实现Etherscan的合约认证的功能 类似这个这个页面
大概实现思路是这样
解决的问题
1. bytecode尾部与链上的bytecode不同
bytecode尾部是一个部署合约元数据的Hash称为 AUXDATA ,不同环境下编译会产生不同的hash(即使使用相同版本编译器),在校对时候需要移除尾部的32字节Hash值
2.bytecode首部与链上的bytecode不同
在编译完成后bytecode首部的一段代码称为部署代码,这一部分在部署完成后通过eth_getCode 是无法获取到的,所以在比对时需要将它移除出去,那么怎么确定哪一部分是属于部署代码的呢?
经过观察发现,部署代码的最后一个指令都会以STOP结尾(不一定正确),在编译合约时同时生成opcodes,编译完成后将opcodes读取进入,截取出opcodes第一个STOP指令前所有的指令,计算出这些指令对应的bytecode,然后将其移除出去,由此又衍生出关于opcodes转bytecode的第三个问题3.opcdoes转bytecode的问题
- 指令转换问题
发现通过opcodes计算的bytecode有时候对有时候不对,问题出现在PUSH指令上,PUSH1 到PUSH32 分别表示操作1到32个字节的数据,那么后面的数据如果不满足PUSH指令的数据长度,需要在高位补充0- 源代码指令不够问题
由于部署代码部分需要自己进行计算,所以需要收集所有的opcodes,以太坊源码 中指定的opcodes在实际使用过程中发现并不完整,经过核对有INVALID,KECCAK256 操作码并没有在该源码文件中,手动录入- 库合约字节码被替换问题
库合约部署完成后,bytecode开头(已经去除了部署代码)使用了PUSH20指令后面紧随合约地址,编译器刚编译完成后当然是不知道合约地址的所以PUSH20指令后面跟随的是空值也就是 0000000000000000000000000000000000000000,检测到后需要替换为真实合约地址
参考文档
https://www.jianshu.com/p/1969f3761208
solidity历史版本下载 nightly版本不知道在哪儿下载,有知道还望的告知一下
{
"STOP": "00",
"ADD": "01",
"MUL": "02",
"SUB": "03",
"DIV": "04",
"SDIV": "05",
"MOD": "06",
"SMOD": "07",
"ADDMOD": "08",
"MULMOD": "09",
"EXP": "0a",
"SIGNEXTEND": "0b",
"LT": "10",
"GT": "11",
"SLT": "12",
"SGT": "13",
"EQ": "14",
"ISZERO": "15",
"AND": "16",
"OR": "17",
"XOR": "18",
"NOT": "19",
"BYTE": "1a",
"SHA3": "20",
"ADDRESS": "30",
"BALANCE": "31",
"ORIGIN": "32",
"CALLER": "33",
"CALLVALUE": "34",
"CALLDATALOAD": "35",
"CALLDATASIZE": "36",
"CALLDATACOPY": "37",
"CODESIZE": "38",
"CODECOPY": "39",
"GASPRICE": "3a",
"EXTCODESIZE": "3b",
"EXTCODECOPY": "3c",
"BLOCKHASH": "40",
"COINBASE": "41",
"TIMESTAMP": "42",
"NUMBER": "43",
"DIFFICULTY": "44",
"GASLIMIT": "45",
"POP": "50",
"MLOAD": "51",
"MSTORE": "52",
"MSTORE8": "53",
"SLOAD": "54",
"SSTORE": "55",
"JUMP": "56",
"JUMPI": "57",
"PC": "58",
"MSIZE": "59",
"GAS": "5a",
"JUMPDEST": "5b",
"PUSH1": "60",
"PUSH2": "61",
"PUSH3": "62",
"PUSH4": "63",
"PUSH5": "64",
"PUSH6": "65",
"PUSH7": "66",
"PUSH8": "67",
"PUSH9": "68",
"PUSH10": "69",
"PUSH11": "6a",
"PUSH12": "6b",
"PUSH13": "6c",
"PUSH14": "6d",
"PUSH15": "6e",
"PUSH16": "6f",
"PUSH17": "70",
"PUSH18": "71",
"PUSH19": "72",
"PUSH20": "73",
"PUSH21": "74",
"PUSH22": "75",
"PUSH23": "76",
"PUSH24": "77",
"PUSH25": "78",
"PUSH26": "79",
"PUSH27": "7a",
"PUSH28": "7b",
"PUSH29": "7c",
"PUSH30": "7d",
"PUSH31": "7e",
"PUSH32": "7f",
"DUP1": "80",
"DUP2": "81",
"DUP3": "82",
"DUP4": "83",
"DUP5": "84",
"DUP6": "85",
"DUP7": "86",
"DUP8": "87",
"DUP9": "88",
"DUP10": "89",
"DUP11": "8a",
"DUP12": "8b",
"DUP13": "8c",
"DUP14": "8d",
"DUP15": "8e",
"DUP16": "8f",
"SWAP1": "90",
"SWAP2": "91",
"SWAP3": "92",
"SWAP4": "93",
"SWAP5": "94",
"SWAP6": "95",
"SWAP7": "96",
"SWAP8": "97",
"SWAP9": "98",
"SWAP10": "99",
"SWAP11": "9a",
"SWAP12": "9b",
"SWAP13": "9c",
"SWAP14": "9d",
"SWAP15": "9e",
"SWAP16": "9f",
"LOG0": "a0",
"LOG1": "a1",
"LOG2": "a2",
"LOG3": "a3",
"LOG4": "a4",
"PUSH": "b0",
"DUP": "b1",
"SWAP": "b2",
"CREATE": "f0",
"CALL": "f1",
"CALLCODE": "f2",
"RETURN": "f3",
"DELEGATECALL": "f4",
"SELFDESTRUCT": "ff",
"REVERT": "fd",
"INVALID": "fe",
"KECCAK256": "20",
"SHL": "1b",
"SHR": "1c",
"SAR": "1d",
"RETURNDATASIZE": "3d",
"RETURNDATACOPY": "3e",
"EXTCODEHASH": "3f",
"CREATE2": "f5",
"STATICCALL": "fa"
}