From 12db1463ac8619bc19d65de27ebc9e8ebd47d644 Mon Sep 17 00:00:00 2001 From: Harry Altman Date: Thu, 9 Apr 2020 15:00:33 -0400 Subject: [PATCH 1/4] Fix allocation of immutables for Solidity 0.6.6 --- packages/codec/lib/ast/types.ts | 2 +- packages/codec/lib/storage/allocate/index.ts | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/codec/lib/ast/types.ts b/packages/codec/lib/ast/types.ts index f4ae8d3aaef..4226990e3db 100644 --- a/packages/codec/lib/ast/types.ts +++ b/packages/codec/lib/ast/types.ts @@ -7,7 +7,7 @@ export interface TypeDescriptions { export interface AstNode { constant?: boolean; - immutable?: boolean; + mutability?: "mutable" | "immutable" | "constant"; //variable, not function, mutability! id: number; name: string; canonicalName?: string; diff --git a/packages/codec/lib/storage/allocate/index.ts b/packages/codec/lib/storage/allocate/index.ts index 1de1c826f51..fc64a1dc5b5 100644 --- a/packages/codec/lib/storage/allocate/index.ts +++ b/packages/codec/lib/storage/allocate/index.ts @@ -322,18 +322,22 @@ function allocateContractState( }) ); + //just in case the constant field ever gets removed + const isConstant = (definition: Ast.AstNode) => + definition.constant || definition.mutability === "constant"; + //now: we split the variables into storage, constant, and code - let [constantVariables, variableVariables] = partition( - variables, - variable => variable.definition.constant + let [constantVariables, variableVariables] = partition(variables, variable => + isConstant(variable.definition) ); //why use this function instead of just checking - //definition.immutable? - //because of a bug in Solidity 0.6.5 that causes the immutable flag + //definition.mutability? + //because of a bug in Solidity 0.6.5 that causes the mutability field //not to exist. So, we also have to check against immutableReferences. const isImmutable = (definition: Ast.AstNode) => - definition.immutable || definition.id.toString() in immutableReferences; + definition.mutability === "immutable" || + definition.id.toString() in immutableReferences; let [immutableVariables, storageVariables] = partition( variableVariables, @@ -410,7 +414,7 @@ function allocateContractState( //now, reweave the three together let contractAllocation: StateVariableAllocation[] = []; for (let variable of variables) { - let arrayToGrabFrom = variable.definition.constant + let arrayToGrabFrom = isConstant(variable.definition) ? constantVariableAllocations : isImmutable(variable.definition) ? immutableVariableAllocations From d33103ca6c7acd9f9b330ff7c32f9c501068b438 Mon Sep 17 00:00:00 2001 From: Harry Altman Date: Thu, 9 Apr 2020 15:09:23 -0400 Subject: [PATCH 2/4] Add test of unused immutable --- packages/debugger/test/data/immutable.js | 9 ++++++++- packages/debugger/test/helpers.js | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/debugger/test/data/immutable.js b/packages/debugger/test/data/immutable.js index d0fdf63d35e..0f766faf775 100644 --- a/packages/debugger/test/data/immutable.js +++ b/packages/debugger/test/data/immutable.js @@ -28,6 +28,7 @@ contract ImmutableTest is Base { bool immutable truth; address immutable self; byte immutable secret; + uint8 immutable trulySecret; event Done(); @@ -36,6 +37,7 @@ contract ImmutableTest is Base { truth = true; self = address(this); secret = 0x88; + trulySecret = 23; emit Done(); //BREAK CONSTRUCTOR } @@ -113,6 +115,10 @@ describe("Immutable state variables", function() { }; assert.deepInclude(variables, expectedResult); + + const trulySecret = await session.variable("trulySecret"); + assert.strictEqual(trulySecret.kind, "error"); + assert.strictEqual(trulySecret.error.kind, "UnusedImmutableError"); }); it("Decodes immutables properly in constructor", async function() { @@ -145,7 +151,8 @@ describe("Immutable state variables", function() { background: "ImmutableTest.Color.Blue", truth: true, self: address, - secret: "0x88" + secret: "0x88", + trulySecret: 23 }; assert.deepInclude(variables, expectedResult); diff --git a/packages/debugger/test/helpers.js b/packages/debugger/test/helpers.js index 3b6e226f528..0e595ea8dbd 100644 --- a/packages/debugger/test/helpers.js +++ b/packages/debugger/test/helpers.js @@ -26,7 +26,7 @@ export async function prepareContracts(provider, sources = {}, migrations) { config.compilers = { solc: { - version: "0.6.5", + version: "0.6.6", settings: { optimizer: { enabled: false, runs: 200 }, evmVersion: "constantinople" From 62df066f33ed2fde1eb5f4bd05b9892d9ab6787a Mon Sep 17 00:00:00 2001 From: Harry Altman Date: Thu, 9 Apr 2020 15:20:20 -0400 Subject: [PATCH 3/4] Update documentation with caveats --- packages/codec/docs/README.md | 22 ++++++++++++++++++++-- packages/decoder/lib/index.ts | 12 ++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/packages/codec/docs/README.md b/packages/codec/docs/README.md index 881a1e58622..cf443b419a7 100644 --- a/packages/codec/docs/README.md +++ b/packages/codec/docs/README.md @@ -86,13 +86,31 @@ which accept decodings in either mode and always return ABI mode. multiple decodings (e.g. [[DecodedLog]]) may contain decodings in different modes. -- You can only decode storage variables in full mode. If full mode fails - while decoding a storage variable, it will throw an exception. +- You can only decode state variables in full mode. If full mode fails + while decoding a state variable, it will throw an exception. - If a contract `Base` declares an event `Event` and a contract `Derived` inheriting from `Base` overrides `Event`, if `Derived` then emits `Base.Event`, ABI mode may not be able to decode it. +#### Additional notes on decoding state variables + +- While internal function pointers can only be decoded in full mode, + full mode still may not be able to determine all the information about + them. Thus, for internal function pointers, you may get a bare-bones + decoding, or you may get a decoding with more information. + +- Solidity 0.6.5 contains a bug that may cause some state variables to + decode incorrectly if there is an immutable state variable which is + written to but never read from. + +- In any version of Solidity, it is impossible to decode an immutable + state variable which is written to but never read from; these will + decode to an error. + +- Not all constant state variables can presently be decoded; some of + these may simply decode to an error. + ---

diff --git a/packages/decoder/lib/index.ts b/packages/decoder/lib/index.ts index 1432a30cec3..b527e9f0c79 100644 --- a/packages/decoder/lib/index.ts +++ b/packages/decoder/lib/index.ts @@ -63,20 +63,16 @@ The decoder outputs lossless, machine-readable [[Format.Values.Result]] objects containing individual decoded values. See the [[Format|format documentation]] for an overview and complete module listing. -Note that for technical reasons, the decoder cannot always fully decode -internal function pointers, but it will do its best even when information is -missing, and will still losslessly return what information it can. If you want -to make sure to get the full information, see the advice -[here](../#decoding-modes) about how to make sure "full mode" works; the same -applies to decoding of internal function pointers. - -### Decoding modes and abification +### Decoding modes, abification, and caveats The decoder runs in either of two modes: full mode or ABI mode. Full mode requires some additional constraints but returns substantially more detailed information. Please see the notes on [decoding modes](../#decoding-modes) for more about this distinction. +See also the notes about [decoding state variables](../#additional-notes-on-decoding-state-variables) for additional +caveats about what may or may not be fully decodable. + ### Basic usage examples #### Decoding a log with the wire decoder From 6e316202492b9ad560e728f07bdba678afc7a128 Mon Sep 17 00:00:00 2001 From: Harry Altman Date: Thu, 9 Apr 2020 16:03:42 -0400 Subject: [PATCH 4/4] Update pragma --- packages/debugger/test/data/immutable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/debugger/test/data/immutable.js b/packages/debugger/test/data/immutable.js index 0f766faf775..e44e17c1393 100644 --- a/packages/debugger/test/data/immutable.js +++ b/packages/debugger/test/data/immutable.js @@ -13,7 +13,7 @@ import * as Codec from "@truffle/codec"; import solidity from "lib/solidity/selectors"; const __IMMUTABLE = ` -pragma solidity ^0.6.5; +pragma solidity ^0.6.6; contract Base { int8 immutable base = -37;