(typesStr: string, hex: string)
| 5 | const WORD_SIZE = 64; |
| 6 | |
| 7 | export function decode(typesStr: string, hex: string): Array<ethereum.Value> { |
| 8 | log.debug('decoding abi type: {}, hex {}', [typesStr, hex]); |
| 9 | if (hex.startsWith('0x')) { |
| 10 | hex = hex.slice(2); |
| 11 | } |
| 12 | |
| 13 | if (typesStr.endsWith(')') && !typesStr.startsWith('(')) { |
| 14 | // the types looks like "someMethod(address,uint8,...)", we need to remove |
| 15 | // the method hash from the hex, as the caller is indicating that we are |
| 16 | // decoding a function call |
| 17 | hex = hex.slice(8); |
| 18 | } |
| 19 | assert(hex.length % 64 == 0, 'hex for abi decoding has odd length ' + hex.length.toString() + ', hex: ' + hex); |
| 20 | |
| 21 | if (typesStr.indexOf('(') > -1) { |
| 22 | typesStr = typesStr.slice(typesStr.indexOf('(') + 1, -1); |
| 23 | } |
| 24 | |
| 25 | let types = typesStr.split(','); |
| 26 | let result: Array<ethereum.Value> = []; |
| 27 | |
| 28 | for (let index = 0; index < types.length; index++) { |
| 29 | let type = types[index]; |
| 30 | let pointer = index * WORD_SIZE; |
| 31 | let word = wordAt(hex, pointer); |
| 32 | let isArray = type.endsWith('[]'); |
| 33 | |
| 34 | log.debug('decoding abi - word at {}: {}', [pointer.toString(), word]); |
| 35 | |
| 36 | if (!isArray) { |
| 37 | if (type == 'address') { |
| 38 | result.push(ethereum.Value.fromAddress(hexToAddress(word))); |
| 39 | } else if (type.startsWith('uint')) { |
| 40 | result.push(ethereum.Value.fromUnsignedBigInt(bigIntFromHex(word))); |
| 41 | } else if (type == 'bool') { |
| 42 | result.push(ethereum.Value.fromBoolean(hexToI32(word) == 1)); |
| 43 | } else if (type == 'bytes') { |
| 44 | let offset = hexToI32(word) * 2; |
| 45 | let length = hexToI32(hex.slice(offset, offset + WORD_SIZE)) * 2; |
| 46 | result.push(ethereum.Value.fromBytes(bytesFromHex(hex.slice(offset + WORD_SIZE, offset + WORD_SIZE + length)))); |
| 47 | } else if (type == 'string') { |
| 48 | let offset = hexToI32(word) * 2; |
| 49 | let length = hexToI32(hex.slice(offset, offset + WORD_SIZE)) * 2; |
| 50 | let utf8Hex = hex.slice(offset + WORD_SIZE, offset + WORD_SIZE + length); |
| 51 | let str = ''; |
| 52 | for (let i = 0; i < utf8Hex.length; i += 2) { |
| 53 | str += String.fromCharCode(hexToI32(utf8Hex.slice(i, i + 2))); |
| 54 | } |
| 55 | log.info('==========> decoding string - bytes: {} string: {}', [utf8Hex, str]); |
| 56 | result.push(ethereum.Value.fromString(str)); |
| 57 | } else { |
| 58 | assert(false, 'decoding ' + type + ' is not yet supported'); |
| 59 | } |
| 60 | } else { |
| 61 | let offset = hexToI32(word) * 2; |
| 62 | let length = hexToI32(hex.slice(offset, offset + WORD_SIZE)) * 2; |
| 63 | if (type.startsWith('uint')) { |
| 64 | let array: Array<BigInt> = []; |
no test coverage detected