diff --git a/packages/abi/src.ts/fragments.ts b/packages/abi/src.ts/fragments.ts index 4602e363d..ac967f6d7 100644 --- a/packages/abi/src.ts/fragments.ts +++ b/packages/abi/src.ts/fragments.ts @@ -50,6 +50,7 @@ type ParseNode = { components?: Array }; +let storageClasses: { [ name: string ]: boolean } = { calldata: true, memory: true, storage: true }; // @TODO: Make sure that children of an indexed tuple are marked with a null indexed function parseParamType(param: string, allowIndexed: boolean): ParseNode { @@ -82,12 +83,15 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode { case ")": delete node.state; - if (allowIndexed) { - if (node.name === "indexed") { - node.indexed = true; - node.name = ""; - } + + if (node.name === "indexed") { + if (!allowIndexed) { throwError(i); } + node.indexed = true; + node.name = ""; } + + if (storageClasses[node.name]) { node.name = ""; } + node.type = verifyType(node.type); let child = node; @@ -101,12 +105,15 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode { case ",": delete node.state; - if (allowIndexed) { - if (node.name === "indexed") { - node.indexed = true; - node.name = ""; - } + + if (node.name === "indexed") { + if (!allowIndexed) { throwError(i); } + node.indexed = true; + node.name = ""; } + + if (storageClasses[node.name]) { node.name = ""; } + node.type = verifyType(node.type); let sibling: ParseNode = newNode(node.parent); @@ -132,12 +139,13 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode { // If reading name, the name is done if (node.state.allowName) { if (node.name !== "") { - if (allowIndexed) { - if (node.name === "indexed") { - if (node.indexed) { throwError(i); } - node.indexed = true; - node.name = ""; - } + if (node.name === "indexed") { + if (!allowIndexed) { throwError(i); } + if (node.indexed) { throwError(i); } + node.indexed = true; + node.name = ""; + } else if (storageClasses[node.name]) { + node.name = ""; } else { node.state.allowName = false; } @@ -186,13 +194,15 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode { delete parent.state; - if (allowIndexed) { - if (node.name === "indexed") { - if (node.indexed) { throwError(originalParam.length - 7); } - node.indexed = true; - node.name = ""; - } + if (node.name === "indexed") { + if (!allowIndexed) { throwError(originalParam.length - 7); } + if (node.indexed) { throwError(originalParam.length - 7); } + node.indexed = true; + node.name = ""; + } else if (storageClasses[node.name]) { + node.name = ""; } + parent.type = verifyType(parent.type); return parent; @@ -476,7 +486,7 @@ function parseModifiers(value: string, params: any): void { params.constant = false; params.payable = false; // @TODO: Should this be initialized to "nonpayable"? - params.stateMutability = null; + params.stateMutability = "nonpayable"; value.split(" ").forEach((modifier) => { switch (modifier.trim()) {