From 8b530040cc16081409d981821b1b895d3da6addc Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Wed, 20 Jul 2022 13:24:16 +0200 Subject: [PATCH] Implemented transient storage in Yul and inline assembly --- docs/grammar/SolidityLexer.g4 | 2 +- libevmasm/Instruction.cpp | 4 ++++ libevmasm/Instruction.h | 3 +++ libevmasm/SemanticInformation.cpp | 2 ++ .../libsolidity/syntaxTests/inlineAssembly/transient.sol | 8 ++++++++ .../syntaxTests/viewPureChecker/tload_not_pure.sol | 9 +++++++++ .../syntaxTests/viewPureChecker/tload_view.sol | 7 +++++++ .../syntaxTests/viewPureChecker/tstore_not_view.sol | 9 +++++++++ test/tools/yulInterpreter/EVMInstructionInterpreter.cpp | 7 +++++++ 9 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/transient.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/tload_not_pure.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/tload_view.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/tstore_not_view.sol diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index 0452f9fa0..ea089747d 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -305,7 +305,7 @@ YulEVMBuiltin: | 'delegatecall' | 'staticcall' | 'return' | 'revert' | 'selfdestruct' | 'invalid' | 'log0' | 'log1' | 'log2' | 'log3' | 'log4' | 'chainid' | 'origin' | 'gasprice' | 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'prevrandao' - | 'gaslimit' | 'basefee'; + | 'gaslimit' | 'basefee' | 'tload' | 'tstore'; YulLBrace: '{' -> pushMode(YulMode); YulRBrace: '}' -> popMode; diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 174d12b5e..d148260f4 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -163,6 +163,8 @@ std::map const solidity::evmasm::c_instructions = { "LOG2", Instruction::LOG2 }, { "LOG3", Instruction::LOG3 }, { "LOG4", Instruction::LOG4 }, + { "TLOAD", Instruction::TLOAD }, + { "TSTORE", Instruction::TSTORE }, { "CREATE", Instruction::CREATE }, { "CALL", Instruction::CALL }, { "CALLCODE", Instruction::CALLCODE }, @@ -312,6 +314,8 @@ static std::map const c_instructionInfo = { Instruction::LOG2, { "LOG2", 0, 4, 0, true, Tier::Special } }, { Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } }, { Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } }, + { Instruction::TLOAD, { "TLOAD", 0, 1, 1, false, Tier::Special} }, + { Instruction::TSTORE, { "TSTORE", 0, 2, 0, true, Tier::Special} }, { Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } }, { Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } }, { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 2fddb11d8..19e2a4976 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -177,6 +177,9 @@ enum class Instruction: uint8_t LOG3, ///< Makes a log entry; 3 topics. LOG4, ///< Makes a log entry; 4 topics. + TLOAD = 0xb3, ///< https://eips.ethereum.org/EIPS/eip-1153 + TSTORE = 0xb4, ///< https://eips.ethereum.org/EIPS/eip-1153 + CREATE = 0xf0, ///< create a new account with associated code CALL, ///< message-call into an account CALLCODE, ///< message-call with another account's code only diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 1971d9d45..5e0967a56 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -486,6 +486,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction) case Instruction::GASLIMIT: case Instruction::STATICCALL: case Instruction::SLOAD: + case Instruction::TLOAD: return true; default: break; @@ -505,6 +506,7 @@ bool SemanticInformation::invalidInViewFunctions(Instruction _instruction) case Instruction::LOG2: case Instruction::LOG3: case Instruction::LOG4: + case Instruction::TSTORE: case Instruction::CREATE: case Instruction::CALL: case Instruction::CALLCODE: diff --git a/test/libsolidity/syntaxTests/inlineAssembly/transient.sol b/test/libsolidity/syntaxTests/inlineAssembly/transient.sol new file mode 100644 index 000000000..22d195d58 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/transient.sol @@ -0,0 +1,8 @@ +contract C { + function f() external returns(uint a) { + assembly { + tstore(0, 13) + a := tload(0) + } + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/tload_not_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/tload_not_pure.sol new file mode 100644 index 000000000..a3b403900 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/tload_not_pure.sol @@ -0,0 +1,9 @@ +contract C { + function f() external pure { + assembly { + pop(tload(0)) + } + } +} +// ---- +// TypeError 2527: (81-89): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/tload_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/tload_view.sol new file mode 100644 index 000000000..731854e1a --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/tload_view.sol @@ -0,0 +1,7 @@ +contract C { + function f() external view returns (uint a) { + assembly { + a := tload(0) + } + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/tstore_not_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/tstore_not_view.sol new file mode 100644 index 000000000..7efb4d970 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/tstore_not_view.sol @@ -0,0 +1,9 @@ +contract C { + function f() external view { + assembly { + tstore(0, 0) + } + } +} +// ---- +// TypeError 8961: (77-89): Function cannot be declared as view because this expression (potentially) modifies the state. diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 132066f4a..1d2906831 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -315,6 +315,13 @@ u256 EVMInstructionInterpreter::eval( accessMemory(arg[0], arg[1]); logTrace(_instruction, arg); return 0; + + case Instruction::TLOAD: + // TODO + return 0; + case Instruction::TSTORE: + // TODO + return 0; // --------------- calls --------------- case Instruction::CREATE: accessMemory(arg[1], arg[2]);