|
14 | 14 | std/tables, |
15 | 15 | results, |
16 | 16 | stint, |
17 | | - stew/[assign2, byteutils], |
18 | | - eth/common/hashes, |
19 | | - web3/encoding |
| 17 | + stew/byteutils, |
| 18 | + eth/common/hashes |
20 | 19 |
|
21 | 20 | export |
22 | 21 | results |
@@ -101,20 +100,42 @@ const panicReasons = { |
101 | 100 | 0x51: "uninitialized function", |
102 | 101 | }.toTable |
103 | 102 |
|
| 103 | +func decodeU256(input: openArray[byte]): Opt[UInt256] = |
| 104 | + if input.len < 32: |
| 105 | + return Opt.none(UInt256) |
| 106 | + Opt.some(UInt256.fromBytesBE(input.toOpenArray(0, 31))) |
| 107 | + |
| 108 | +func decodeString(input: openArray[byte]): Opt[string] = |
| 109 | + let |
| 110 | + offset256 = ?decodeU256(input) |
| 111 | + offset = offset256.truncate(int) |
| 112 | + |
| 113 | + if offset >= input.len: |
| 114 | + return Opt.none(string) |
| 115 | + |
| 116 | + let |
| 117 | + len256 = ?decodeU256(input.toOpenArray(offset, input.len-1)) |
| 118 | + len = len256.truncate(int) |
| 119 | + dataOffset = offset + 32 |
| 120 | + |
| 121 | + if dataOffset + len >= input.len: |
| 122 | + return Opt.none(string) |
| 123 | + |
| 124 | + ok(string.fromBytes(input.toOpenArray(dataOffset, dataOffset + len - 1))) |
| 125 | + |
104 | 126 | # UnpackRevert resolves the abi-encoded revert reason. According to the solidity |
105 | 127 | # spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert, |
106 | 128 | # the provided revert reason is abi-encoded as if it were a call to function |
107 | 129 | # `Error(string)` or `Panic(uint256)`. |
108 | | -proc unpackRevertReason*(data: openArray[byte], reason: var string) = |
| 130 | +proc unpackRevertReason*(data: openArray[byte]): Opt[string] = |
109 | 131 | if data.len() < 4: |
110 | | - reason = "" |
111 | | - return |
| 132 | + return Opt.none(string) |
112 | 133 |
|
113 | 134 | let selector = data[0..3] |
114 | 135 |
|
115 | 136 | if selector == revertSelector: |
116 | | - discard decode(data.toOpenArray(4, data.len() - 1), 0, 0, reason) |
| 137 | + return decodeString(data.toOpenArray(4, data.len() - 1)) |
117 | 138 | elif selector == panicSelector: |
118 | | - var reasonCode: UInt256 |
119 | | - discard decode(data.toOpenArray(4, data.len() - 1), 0, 0, reasonCode) |
120 | | - assign(reason, panicReasons.getOrDefault(reasonCode.truncate(int))) |
| 139 | + let reasonCode = decodeU256(data.toOpenArray(4, data.len() - 1)).valueOr: |
| 140 | + return Opt.none(string) |
| 141 | + return ok(panicReasons.getOrDefault(reasonCode.truncate(int))) |
0 commit comments