From 1ee4b9dc3b753cb40e981072ac9643df4fc5e11a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 10 Dec 2019 23:50:01 +0000 Subject: [PATCH 1/6] Remove the LLL compiler --- CMakeLists.txt | 7 - cmake/EthOptions.cmake | 1 - liblll/CMakeLists.txt | 14 - liblll/CodeFragment.cpp | 758 -------------------- liblll/CodeFragment.h | 68 -- liblll/Compiler.cpp | 126 ---- liblll/Compiler.h | 40 -- liblll/CompilerState.cpp | 86 --- liblll/CompilerState.h | 54 -- liblll/Exceptions.h | 42 -- liblll/Parser.cpp | 156 ----- liblll/Parser.h | 39 -- lllc/CMakeLists.txt | 19 - lllc/main.cpp | 157 ----- test/CMakeLists.txt | 19 - test/boostTest.cpp | 5 - test/liblll/Compiler.cpp | 670 ------------------ test/liblll/EndToEndTest.cpp | 1026 ---------------------------- test/liblll/ExecutionFramework.cpp | 33 - test/liblll/ExecutionFramework.h | 69 -- test/liblll/LLL_ENS.cpp | 503 -------------- test/liblll/LLL_ERC20.cpp | 652 ------------------ test/liblll/Parser.cpp | 181 ----- 23 files changed, 4725 deletions(-) delete mode 100644 liblll/CMakeLists.txt delete mode 100644 liblll/CodeFragment.cpp delete mode 100644 liblll/CodeFragment.h delete mode 100644 liblll/Compiler.cpp delete mode 100644 liblll/Compiler.h delete mode 100644 liblll/CompilerState.cpp delete mode 100644 liblll/CompilerState.h delete mode 100644 liblll/Exceptions.h delete mode 100644 liblll/Parser.cpp delete mode 100644 liblll/Parser.h delete mode 100644 lllc/CMakeLists.txt delete mode 100644 lllc/main.cpp delete mode 100644 test/liblll/Compiler.cpp delete mode 100644 test/liblll/EndToEndTest.cpp delete mode 100644 test/liblll/ExecutionFramework.cpp delete mode 100644 test/liblll/ExecutionFramework.h delete mode 100644 test/liblll/LLL_ENS.cpp delete mode 100644 test/liblll/LLL_ERC20.cpp delete mode 100644 test/liblll/Parser.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a112deaa..f64c7bd94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,10 +19,7 @@ if (IS_BIG_ENDIAN) message(FATAL_ERROR "${PROJECT_NAME} currently does not support big endian systems.") endif() -option(LLL "Build LLL" OFF) option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) -option(LLLC_LINK_STATIC "Link lllc executable statically on supported platforms" OFF) -option(INSTALL_LLLC "Include lllc executable in installation" ${LLL}) # Setup cccache. include(EthCcache) @@ -61,10 +58,6 @@ add_subdirectory(libsolc) if (NOT EMSCRIPTEN) add_subdirectory(solc) - if (LLL) - add_subdirectory(liblll) - add_subdirectory(lllc) - endif() endif() if (TESTS AND NOT EMSCRIPTEN) diff --git a/cmake/EthOptions.cmake b/cmake/EthOptions.cmake index 6dca5e1be..cd6fe8133 100644 --- a/cmake/EthOptions.cmake +++ b/cmake/EthOptions.cmake @@ -41,7 +41,6 @@ if (SUPPORT_TOOLS) endif() message("------------------------------------------------------------------ flags") message("-- OSSFUZZ ${OSSFUZZ}") - message("-- LLL ${LLL}") message("------------------------------------------------------------------------") message("") endmacro() diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt deleted file mode 100644 index a6c8f3a9a..000000000 --- a/liblll/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(sources - CodeFragment.cpp - CodeFragment.h - Compiler.cpp - Compiler.h - CompilerState.cpp - CompilerState.h - Exceptions.h - Parser.cpp - Parser.h -) - -add_library(lll ${sources}) -target_link_libraries(lll PUBLIC evmasm solutil) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp deleted file mode 100644 index 556f3dcf6..000000000 --- a/liblll/CodeFragment.cpp +++ /dev/null @@ -1,758 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file CodeFragment.cpp - * @author Gav Wood - * @date 2014 - */ - -#include -#include -#include -#include -#include - -#include - -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif // defined(__GNUC__) - -#include - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif // defined(__GNUC__) - - -using namespace std; -using namespace solidity; -using namespace solidity::util; -using namespace solidity::evmasm; -using namespace solidity::lll; - -void CodeFragment::finalise(CompilerState const& _cs) -{ - // NOTE: add this as a safeguard in case the user didn't issue an - // explicit stop at the end of the sequence - m_asm.append(Instruction::STOP); - - if (_cs.usedAlloc && _cs.vars.size() && !m_finalised) - { - m_finalised = true; - m_asm.injectStart(Instruction::MSTORE8); - m_asm.injectStart((u256)((_cs.vars.size() + 2) * 32) - 1); - m_asm.injectStart((u256)1); - } -} - -namespace -{ -/// Returns true iff the instruction is valid in "inline assembly". -bool validAssemblyInstruction(string us) -{ - auto it = c_instructions.find(us); - return !( - it == c_instructions.end() || - isPushInstruction(it->second) - ); -} - -/// Returns true iff the instruction is valid as a function. -bool validFunctionalInstruction(string us) -{ - auto it = c_instructions.find(us); - return !( - it == c_instructions.end() || - isPushInstruction(it->second) || - isDupInstruction(it->second) || - isSwapInstruction(it->second) || - it->second == Instruction::JUMPDEST - ); -} -} - -CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback const& _readFile, bool _allowASM): - m_readFile(_readFile) -{ -/* - std::cout << "CodeFragment. Locals:"; - for (auto const& i: _s.defs) - std::cout << i.first << ":" << i.second.m_asm.out(); - std::cout << "Args:"; - for (auto const& i: _s.args) - std::cout << i.first << ":" << i.second.m_asm.out(); - std::cout << "Outers:"; - for (auto const& i: _s.outers) - std::cout << i.first << ":" << i.second.m_asm.out(); - debugOutAST(std::cout, _t); - std::cout << endl << flush; -*/ - switch (_t.which()) - { - case sp::utree_type::list_type: - constructOperation(_t, _s); - break; - case sp::utree_type::string_type: - { - auto sr = _t.get, sp::utree_type::string_type>>(); - string s(sr.begin(), sr.end()); - m_asm.append(s); - break; - } - case sp::utree_type::symbol_type: - { - auto sr = _t.get, sp::utree_type::symbol_type>>(); - string s(sr.begin(), sr.end()); - string us = boost::algorithm::to_upper_copy(s); - if (_allowASM && c_instructions.count(us) && validAssemblyInstruction(us)) - m_asm.append(c_instructions.at(us)); - else if (_s.defs.count(s)) - m_asm.append(_s.defs.at(s).m_asm); - else if (_s.args.count(s)) - m_asm.append(_s.args.at(s).m_asm); - else if (_s.outers.count(s)) - m_asm.append(_s.outers.at(s).m_asm); - else if (us.find_first_of("1234567890") != 0 && us.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNM1234567890_-") == string::npos) - { - auto it = _s.vars.find(s); - if (it == _s.vars.end()) - error(std::string("Symbol not found: ") + s); - m_asm.append((u256)it->second.first); - } - else - error(s); - - break; - } - case sp::utree_type::any_type: - { - bigint i = *_t.get(); - if (i < 0 || i > bigint(u256(0) - 1)) - error(toString(i)); - m_asm.append((u256)i); - break; - } - default: - error("Unexpected fragment type"); - break; - } -} - -void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) -{ - if (_t.tag() == 0 && _t.empty()) - error(); - else if (_t.tag() == 0 && _t.front().which() != sp::utree_type::symbol_type) - error(); - else - { - string s; - string us; - switch (_t.tag()) - { - case 0: - { - auto sr = _t.front().get, sp::utree_type::symbol_type>>(); - s = string(sr.begin(), sr.end()); - us = boost::algorithm::to_upper_copy(s); - break; - } - case 1: - us = "MLOAD"; - break; - case 2: - us = "SLOAD"; - break; - case 3: - us = "MSTORE"; - break; - case 4: - us = "SSTORE"; - break; - case 5: - us = "SEQ"; - break; - case 6: - us = "CALLDATALOAD"; - break; - default:; - } - - auto firstAsString = [&]() - { - auto i = *++_t.begin(); - if (i.tag()) - error(toString(i)); - if (i.which() == sp::utree_type::string_type) - { - auto sr = i.get, sp::utree_type::string_type>>(); - return string(sr.begin(), sr.end()); - } - else if (i.which() == sp::utree_type::symbol_type) - { - auto sr = i.get, sp::utree_type::symbol_type>>(); - return _s.getDef(string(sr.begin(), sr.end())).m_asm.backString(); - } - return string(); - }; - - auto varAddress = [&](string const& n, bool createMissing = false) - { - if (n.empty()) - error("Empty variable name not allowed"); - auto it = _s.vars.find(n); - if (it == _s.vars.end()) - { - if (createMissing) - { - // Create new variable - bool ok; - tie(it, ok) = _s.vars.insert(make_pair(n, make_pair(_s.stackSize, 32))); - _s.stackSize += 32; - } - else - error(std::string("Symbol not found: ") + n); - } - return it->second.first; - }; - - // Operations who args are not standard stack-pushers. - bool nonStandard = true; - if (us == "ASM") - { - int c = 0; - for (auto const& i: _t) - if (c++) - { - auto fragment = CodeFragment(i, _s, m_readFile, true).m_asm; - if ((m_asm.deposit() + fragment.deposit()) < 0) - error("The assembly instruction resulted in stack underflow"); - m_asm.append(fragment); - } - } - else if (us == "INCLUDE") - { - if (_t.size() != 2) - error(us); - string fileName = firstAsString(); - if (fileName.empty()) - error("Empty file name provided"); - if (!m_readFile) - error("Import callback not present"); - string contents = m_readFile(fileName); - if (contents.empty()) - error(std::string("File not found (or empty): ") + fileName); - m_asm.append(CodeFragment::compile(std::move(contents), _s, m_readFile).m_asm); - } - else if (us == "SET") - { - // TODO: move this to be a stack variable (and not a memory variable) - if (_t.size() != 3) - error(us); - int c = 0; - for (auto const& i: _t) - if (c++ == 2) - m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm); - m_asm.append((u256)varAddress(firstAsString(), true)); - m_asm.append(Instruction::MSTORE); - } - else if (us == "UNSET") - { - // TODO: this doesn't actually free up anything, since it is a memory variable (see "SET") - if (_t.size() != 2) - error(); - auto it = _s.vars.find(firstAsString()); - if (it != _s.vars.end()) - _s.vars.erase(it); - } - else if (us == "GET") - { - if (_t.size() != 2) - error(us); - m_asm.append((u256)varAddress(firstAsString())); - m_asm.append(Instruction::MLOAD); - } - else if (us == "WITH") - { - if (_t.size() != 4) - error(); - string key = firstAsString(); - if (_s.vars.find(key) != _s.vars.end()) - error(string("Symbol already used: ") + key); - - // Create variable - // TODO: move this to be a stack variable (and not a memory variable) - size_t c = 0; - for (auto const& i: _t) - if (c++ == 2) - m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm); - m_asm.append((u256)varAddress(key, true)); - m_asm.append(Instruction::MSTORE); - - // Insert sub with variable access, but new state - CompilerState ns = _s; - c = 0; - for (auto const& i: _t) - if (c++ == 3) - m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm); - - // Remove variable - auto it = _s.vars.find(key); - if (it != _s.vars.end()) - _s.vars.erase(it); - } - else if (us == "REF") - m_asm.append((u256)varAddress(firstAsString())); - else if (us == "DEF") - { - string n; - unsigned ii = 0; - if (_t.size() != 3 && _t.size() != 4) - error(us); - vector args; - for (auto const& i: _t) - { - if (ii == 1) - { - if (i.tag()) - error(toString(i)); - if (i.which() == sp::utree_type::string_type) - { - auto sr = i.get, sp::utree_type::string_type>>(); - n = string(sr.begin(), sr.end()); - } - else if (i.which() == sp::utree_type::symbol_type) - { - auto sr = i.get, sp::utree_type::symbol_type>>(); - n = _s.getDef(string(sr.begin(), sr.end())).m_asm.backString(); - } - } - else if (ii == 2) - if (_t.size() == 3) - { - /// NOTE: some compilers could do the assignment first if this is done in a single line - CodeFragment code = CodeFragment(i, _s, m_readFile); - _s.defs[n] = code; - } - else - for (auto const& j: i) - { - if (j.tag() || j.which() != sp::utree_type::symbol_type) - error(); - auto sr = j.get, sp::utree_type::symbol_type>>(); - args.emplace_back(sr.begin(), sr.end()); - } - else if (ii == 3) - { - auto k = make_pair(n, args.size()); - _s.macros[k].code = i; - _s.macros[k].env = _s.outers; - _s.macros[k].args = args; - for (auto const& i: _s.args) - _s.macros[k].env[i.first] = i.second; - for (auto const& i: _s.defs) - _s.macros[k].env[i.first] = i.second; - } - ++ii; - } - } - else if (us == "LIT") - { - if (_t.size() < 3) - error(us); - unsigned ii = 0; - CodeFragment pos; - bytes data; - for (auto const& i: _t) - { - if (ii == 0) - { - ii++; - continue; - } - else if (ii == 1) - { - pos = CodeFragment(i, _s, m_readFile); - if (pos.m_asm.deposit() != 1) - error(toString(i)); - } - else if (i.tag() != 0) - { - error(toString(i)); - } - else if (i.which() == sp::utree_type::string_type) - { - auto sr = i.get, sp::utree_type::string_type>>(); - data.insert(data.end(), (uint8_t const *)sr.begin(), (uint8_t const*)sr.end()); - } - else if (i.which() == sp::utree_type::any_type) - { - bigint bi = *i.get(); - if (bi < 0) - error(toString(i)); - else - { - bytes tmp = toCompactBigEndian(bi); - data.insert(data.end(), tmp.begin(), tmp.end()); - } - } - else - { - error(toString(i)); - } - - ii++; - } - m_asm.append((u256)data.size()); - m_asm.append(Instruction::DUP1); - m_asm.append(data); - m_asm.append(pos.m_asm, 1); - m_asm.append(Instruction::CODECOPY); - } - else - nonStandard = false; - - if (nonStandard) - return; - - std::map const c_arith = { - { "+", Instruction::ADD }, - { "-", Instruction::SUB }, - { "*", Instruction::MUL }, - { "/", Instruction::DIV }, - { "%", Instruction::MOD }, - { "&", Instruction::AND }, - { "|", Instruction::OR }, - { "^", Instruction::XOR } - }; - std::map> const c_binary = { - { "<", { Instruction::LT, false } }, - { "<=", { Instruction::GT, true } }, - { ">", { Instruction::GT, false } }, - { ">=", { Instruction::LT, true } }, - { "S<", { Instruction::SLT, false } }, - { "S<=", { Instruction::SGT, true } }, - { "S>", { Instruction::SGT, false } }, - { "S>=", { Instruction::SLT, true } }, - { "=", { Instruction::EQ, false } }, - { "!=", { Instruction::EQ, true } } - }; - std::map const c_unary = { - { "!", Instruction::ISZERO }, - { "~", Instruction::NOT } - }; - - vector code; - CompilerState ns = _s; - ns.vars.clear(); - ns.usedAlloc = false; - int c = _t.tag() ? 1 : 0; - for (auto const& i: _t) - if (c++) - { - if (us == "LLL" && c == 1) - code.emplace_back(i, ns, m_readFile); - else - code.emplace_back(i, _s, m_readFile); - } - auto requireSize = [&](unsigned s) { if (code.size() != s) error(us); }; - auto requireMinSize = [&](unsigned s) { if (code.size() < s) error(us); }; - auto requireMaxSize = [&](unsigned s) { if (code.size() > s) error(us); }; - auto requireDeposit = [&](unsigned i, int s) { if (code[i].m_asm.deposit() != s) error(us); }; - - if (_s.macros.count(make_pair(s, code.size()))) - { - Macro const& m = _s.macros.at(make_pair(s, code.size())); - CompilerState cs = _s; - for (auto const& i: m.env) - cs.outers[i.first] = i.second; - for (auto const& i: cs.defs) - cs.outers[i.first] = i.second; - cs.defs.clear(); - for (unsigned i = 0; i < m.args.size(); ++i) - { - //requireDeposit(i, 1); - cs.args[m.args[i]] = code[i]; - } - m_asm.append(CodeFragment(m.code, cs, m_readFile).m_asm); - for (auto const& i: cs.defs) - _s.defs[i.first] = i.second; - for (auto const& i: cs.macros) - _s.macros.insert(i); - } - else if (c_instructions.count(us) && validFunctionalInstruction(us)) - { - auto it = c_instructions.find(us); - requireSize(instructionInfo(it->second).args); - - for (unsigned i = code.size(); i; --i) - m_asm.append(code[i - 1].m_asm, 1); - m_asm.append(it->second); - } - else if (c_arith.count(us)) - { - auto it = c_arith.find(us); - requireMinSize(1); - for (unsigned i = code.size(); i; --i) - { - requireDeposit(i - 1, 1); - m_asm.append(code[i - 1].m_asm, 1); - } - for (unsigned i = 1; i < code.size(); ++i) - m_asm.append(it->second); - } - else if (c_binary.count(us)) - { - auto it = c_binary.find(us); - requireSize(2); - requireDeposit(0, 1); - requireDeposit(1, 1); - m_asm.append(code[1].m_asm, 1); - m_asm.append(code[0].m_asm, 1); - m_asm.append(it->second.first); - if (it->second.second) - m_asm.append(Instruction::ISZERO); - } - else if (c_unary.count(us)) - { - auto it = c_unary.find(us); - requireSize(1); - requireDeposit(0, 1); - m_asm.append(code[0].m_asm, 1); - m_asm.append(it->second); - } - else if (us == "IF") - { - requireSize(3); - requireDeposit(0, 1); - int minDep = min(code[1].m_asm.deposit(), code[2].m_asm.deposit()); - - m_asm.append(code[0].m_asm); - auto mainBranch = m_asm.appendJumpI(); - - /// The else branch. - int startDeposit = m_asm.deposit(); - m_asm.append(code[2].m_asm, minDep); - auto end = m_asm.appendJump(); - int deposit = m_asm.deposit(); - m_asm.setDeposit(startDeposit); - - /// The main branch. - m_asm << mainBranch.tag(); - m_asm.append(code[1].m_asm, minDep); - m_asm << end.tag(); - if (m_asm.deposit() != deposit) - error(us); - } - else if (us == "WHEN" || us == "UNLESS") - { - requireSize(2); - requireDeposit(0, 1); - - m_asm.append(code[0].m_asm); - if (us == "WHEN") - m_asm.append(Instruction::ISZERO); - auto end = m_asm.appendJumpI(); - m_asm.append(code[1].m_asm, 0); - m_asm << end.tag(); - } - else if (us == "WHILE" || us == "UNTIL") - { - requireSize(2); - requireDeposit(0, 1); - - auto begin = m_asm.append(m_asm.newTag()); - m_asm.append(code[0].m_asm); - if (us == "WHILE") - m_asm.append(Instruction::ISZERO); - auto end = m_asm.appendJumpI(); - m_asm.append(code[1].m_asm, 0); - m_asm.appendJump(begin); - m_asm << end.tag(); - } - else if (us == "FOR") - { - requireSize(4); - requireDeposit(1, 1); - - m_asm.append(code[0].m_asm, 0); - auto begin = m_asm.append(m_asm.newTag()); - m_asm.append(code[1].m_asm); - m_asm.append(Instruction::ISZERO); - auto end = m_asm.appendJumpI(); - m_asm.append(code[3].m_asm, 0); - m_asm.append(code[2].m_asm, 0); - m_asm.appendJump(begin); - m_asm << end.tag(); - } - else if (us == "SWITCH") - { - requireMinSize(1); - - bool hasDefault = (code.size() % 2 == 1); - int startDeposit = m_asm.deposit(); - int targetDeposit = hasDefault ? code[code.size() - 1].m_asm.deposit() : 0; - - // The conditions - evmasm::AssemblyItems jumpTags; - for (unsigned i = 0; i < code.size() - 1; i += 2) - { - requireDeposit(i, 1); - m_asm.append(code[i].m_asm); - jumpTags.push_back(m_asm.appendJumpI()); - } - - // The default, if present - if (hasDefault) - m_asm.append(code[code.size() - 1].m_asm); - - // The targets - appending in reverse makes the top case the most efficient. - if (code.size() > 1) - { - auto end = m_asm.appendJump(); - for (int i = 2 * (code.size() / 2 - 1); i >= 0; i -= 2) - { - m_asm << jumpTags[i / 2].tag(); - requireDeposit(i + 1, targetDeposit); - m_asm.append(code[i + 1].m_asm); - if (i != 0) - m_asm.appendJump(end); - } - m_asm << end.tag(); - } - - m_asm.setDeposit(startDeposit + targetDeposit); - } - else if (us == "ALLOC") - { - requireSize(1); - requireDeposit(0, 1); - - // (alloc N): - // - Evaluates to (msize) before the allocation - the start of the allocated memory - // - Does not allocate memory when N is zero - // - Size of memory allocated is N bytes rounded up to a multiple of 32 - // - Uses MLOAD to expand MSIZE to avoid modifying memory. - - auto end = m_asm.newTag(); - m_asm.append(Instruction::MSIZE); // Result will be original top of memory - m_asm.append(code[0].m_asm, 1); // The alloc argument N - m_asm.append(Instruction::DUP1); - m_asm.append(Instruction::ISZERO);// (alloc 0) does not change MSIZE - m_asm.appendJumpI(end); - m_asm.append(u256(1)); - m_asm.append(Instruction::DUP2); // Copy N - m_asm.append(Instruction::SUB); // N-1 - m_asm.append(u256(0x1f)); // Bit mask - m_asm.append(Instruction::NOT); // Invert - m_asm.append(Instruction::AND); // Align N-1 on 32 byte boundary - m_asm.append(Instruction::MSIZE); // MSIZE is cheap - m_asm.append(Instruction::ADD); - m_asm.append(Instruction::MLOAD); // Updates MSIZE - m_asm.append(Instruction::POP); // Discard the result of the MLOAD - m_asm.append(end); - m_asm.append(Instruction::POP); // Discard duplicate N - - _s.usedAlloc = true; - } - else if (us == "LLL") - { - requireMinSize(2); - requireMaxSize(3); - requireDeposit(1, 1); - - auto subPush = m_asm.appendSubroutine(make_shared(code[0].assembly(ns))); - m_asm.append(Instruction::DUP1); - if (code.size() == 3) - { - requireDeposit(2, 1); - m_asm.append(code[2].m_asm, 1); - m_asm.append(Instruction::LT); - m_asm.append(Instruction::ISZERO); - m_asm.append(Instruction::MUL); - m_asm.append(Instruction::DUP1); - } - m_asm.append(subPush); - m_asm.append(code[1].m_asm, 1); - m_asm.append(Instruction::CODECOPY); - } - else if (us == "&&" || us == "||") - { - requireMinSize(1); - for (unsigned i = 0; i < code.size(); ++i) - requireDeposit(i, 1); - - auto end = m_asm.newTag(); - if (code.size() > 1) - { - m_asm.append((u256)(us == "||" ? 1 : 0)); - for (unsigned i = 1; i < code.size(); ++i) - { - // Check if true - predicate - m_asm.append(code[i - 1].m_asm, 1); - if (us == "&&") - m_asm.append(Instruction::ISZERO); - m_asm.appendJumpI(end); - } - m_asm.append(Instruction::POP); - } - - // Check if true - predicate - m_asm.append(code.back().m_asm, 1); - - // At end now. - m_asm.append(end); - } - else if (us == "SEQ") - { - unsigned ii = 0; - for (auto const& i: code) - if (++ii < code.size()) - m_asm.append(i.m_asm, 0); - else - m_asm.append(i.m_asm); - } - else if (us == "RAW") - { - for (auto const& i: code) - m_asm.append(i.m_asm); - // Leave only the last item on stack. - while (m_asm.deposit() > 1) - m_asm.append(Instruction::POP); - } - else if (us == "BYTECODESIZE") - { - m_asm.appendProgramSize(); - } - else if (us.find_first_of("1234567890") != 0 && us.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNM1234567890_-") == string::npos) - m_asm.append((u256)varAddress(s)); - else - error("Unsupported keyword: '" + us + "'"); - } -} - -CodeFragment CodeFragment::compile(string _src, CompilerState& _s, ReadCallback const& _readFile) -{ - CodeFragment ret; - sp::utree o; - parseTreeLLL(std::move(_src), o); - if (!o.empty()) - ret = CodeFragment(o, _s, _readFile); - _s.treesToKill.push_back(o); - return ret; -} diff --git a/liblll/CodeFragment.h b/liblll/CodeFragment.h deleted file mode 100644 index 894c91821..000000000 --- a/liblll/CodeFragment.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file CodeFragment.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include -#include -#include - -namespace boost { namespace spirit { class utree; } } -namespace sp = boost::spirit; - -namespace solidity::lll -{ - -struct CompilerState; - -class CodeFragment -{ -public: - using ReadCallback = std::function; - - CodeFragment() = default; - CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback const& _readFile, bool _allowASM = false); - - static CodeFragment compile(std::string _src, CompilerState& _s, ReadCallback const& _readFile); - - /// Consolidates data and compiles code. - evmasm::Assembly& assembly(CompilerState const& _cs) { finalise(_cs); return m_asm; } - -private: - void finalise(CompilerState const& _cs); - - template static void error() { BOOST_THROW_EXCEPTION(T() ); } - template static void error(std::string const& reason) { - auto err = T(); - err << util::errinfo_comment(reason); - BOOST_THROW_EXCEPTION(err); - } - void constructOperation(sp::utree const& _t, CompilerState& _s); - - bool m_finalised = false; - evmasm::Assembly m_asm; - ReadCallback m_readFile; -}; - -static CodeFragment const NullCodeFragment; - -} diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp deleted file mode 100644 index a1ccf47d6..000000000 --- a/liblll/Compiler.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file Compiler.cpp - * @author Gav Wood - * @date 2014 - */ - -#include -#include -#include -#include - -using namespace std; -using namespace solidity; -using namespace solidity::util; -using namespace solidity::lll; - -bytes solidity::lll::compileLLL(string _src, langutil::EVMVersion _evmVersion, bool _opt, std::vector* _errors, ReadCallback const& _readFile) -{ - try - { - CompilerState cs; - cs.populateStandard(); - auto assembly = CodeFragment::compile(std::move(_src), cs, _readFile).assembly(cs); - if (_opt) - assembly = assembly.optimise(true, _evmVersion, true, 200); - bytes ret = assembly.assemble().bytecode; - for (auto i: cs.treesToKill) - killBigints(i); - return ret; - } - catch (Exception const& _e) - { - if (_errors) - { - _errors->emplace_back("Parse error."); - _errors->emplace_back(boost::diagnostic_information(_e)); - } - } - catch (std::exception const& _e) - { - if (_errors) - { - _errors->emplace_back("Parse exception."); - _errors->emplace_back(boost::diagnostic_information(_e)); - } - } - catch (...) - { - if (_errors) - _errors->emplace_back("Internal compiler exception."); - } - return bytes(); -} - -std::string solidity::lll::compileLLLToAsm(std::string _src, langutil::EVMVersion _evmVersion, bool _opt, std::vector* _errors, ReadCallback const& _readFile) -{ - try - { - CompilerState cs; - cs.populateStandard(); - auto assembly = CodeFragment::compile(std::move(_src), cs, _readFile).assembly(cs); - if (_opt) - assembly = assembly.optimise(true, _evmVersion, true, 200); - string ret = assembly.assemblyString(); - for (auto i: cs.treesToKill) - killBigints(i); - return ret; - } - catch (Exception const& _e) - { - if (_errors) - { - _errors->emplace_back("Parse error."); - _errors->emplace_back(boost::diagnostic_information(_e)); - } - } - catch (std::exception const& _e) - { - if (_errors) - { - _errors->emplace_back("Parse exception."); - _errors->emplace_back(boost::diagnostic_information(_e)); - } - } - catch (...) - { - if (_errors) - _errors->emplace_back("Internal compiler exception."); - } - return string(); -} - -string solidity::lll::parseLLL(string _src) -{ - sp::utree o; - - try - { - parseTreeLLL(std::move(_src), o); - } - catch (...) - { - killBigints(o); - return string(); - } - - ostringstream ret; - debugOutAST(ret, o); - killBigints(o); - return ret.str(); -} diff --git a/liblll/Compiler.h b/liblll/Compiler.h deleted file mode 100644 index 8d2989ce5..000000000 --- a/liblll/Compiler.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file Compiler.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include - -#include - -#include -#include - -namespace solidity::lll -{ - -using ReadCallback = std::function; - -std::string parseLLL(std::string _src); -std::string compileLLLToAsm(std::string _src, langutil::EVMVersion _evmVersion, bool _opt = true, std::vector* _errors = nullptr, ReadCallback const& _readFile = ReadCallback()); -bytes compileLLL(std::string _src, langutil::EVMVersion _evmVersion, bool _opt = true, std::vector* _errors = nullptr, ReadCallback const& _readFile = ReadCallback()); - -} diff --git a/liblll/CompilerState.cpp b/liblll/CompilerState.cpp deleted file mode 100644 index b35763ca5..000000000 --- a/liblll/CompilerState.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file CompilerState.cpp - * @author Gav Wood - * @date 2014 - */ - -#include -#include - -using namespace std; -using namespace solidity; -using namespace solidity::lll; - -CompilerState::CompilerState() -{ -} - -CodeFragment const& CompilerState::getDef(std::string const& _s) const -{ - if (defs.count(_s)) - return defs.at(_s); - else if (args.count(_s)) - return args.at(_s); - else if (outers.count(_s)) - return outers.at(_s); - else - return NullCodeFragment; -} - -void CompilerState::populateStandard() -{ - static string const s = "{" - "(def 'panic () (asm INVALID))" - // Alternative macro version of alloc, which is currently implemented in the parser - // "(def 'alloc (n) (raw (msize) (when n (pop (mload (+ (msize) (& (- n 1) (~ 0x1f))))))))" - "(def 'allgas (- (gas) 21))" - "(def 'send (to value) (call allgas to value 0 0 0 0))" - "(def 'send (gaslimit to value) (call gaslimit to value 0 0 0 0))" - // NOTE: in this macro, memory location 0 is set in order to force msize to be at least 32 bytes. - "(def 'msg (gaslimit to value data datasize outsize) { [0]:0 [0]:(msize) (call gaslimit to value data datasize @0 outsize) @0 })" - "(def 'msg (gaslimit to value data datasize) { (call gaslimit to value data datasize 0 32) @0 })" - "(def 'msg (gaslimit to value data) { [0]:data (msg gaslimit to value 0 32) })" - "(def 'msg (to value data) { [0]:data (msg allgas to value 0 32) })" - "(def 'msg (to data) { [0]:data (msg allgas to 0 0 32) })" - // NOTE: in the create macros, memory location 0 is set in order to force msize to be at least 32 bytes. - "(def 'create (value code) { [0]:0 [0]:(msize) (create value @0 (lll code @0)) })" - "(def 'create (code) { [0]:0 [0]:(msize) (create 0 @0 (lll code @0)) })" - "(def 'sha3 (loc len) (keccak256 loc len))" - "(def 'sha3 (val) { [0]:val (sha3 0 32) })" - "(def 'sha3pair (a b) { [0]:a [32]:b (sha3 0 64) })" - "(def 'sha3trip (a b c) { [0]:a [32]:b [64]:c (sha3 0 96) })" - "(def 'return (val) { [0]:val (return 0 32) })" - "(def 'returnlll (code) (return 0 (lll code 0)) )" - "(def 'makeperm (name pos) { (def name (sload pos)) (def name (v) (sstore pos v)) } )" - "(def 'permcount 0)" - "(def 'perm (name) { (makeperm name permcount) (def 'permcount (+ permcount 1)) } )" - "(def 'ecrecover (hash v r s) { [0] hash [32] v [64] r [96] s (msg allgas 1 0 0 128) })" - "(def 'sha256 (data datasize) (msg allgas 2 0 data datasize))" - "(def 'ripemd160 (data datasize) (msg allgas 3 0 data datasize))" - "(def 'sha256 (val) { [0]:val (sha256 0 32) })" - "(def 'ripemd160 (val) { [0]:val (ripemd160 0 32) })" - "(def 'wei 1)" - "(def 'szabo 1000000000000)" - "(def 'finney 1000000000000000)" - "(def 'ether 1000000000000000000)" - // these could be replaced by native instructions once supported by EVM - "(def 'shl (val shift) (mul val (exp 2 shift)))" - "(def 'shr (val shift) (div val (exp 2 shift)))" - "}"; - CodeFragment::compile(s, *this, CodeFragment::ReadCallback()); -} diff --git a/liblll/CompilerState.h b/liblll/CompilerState.h deleted file mode 100644 index 2313272b1..000000000 --- a/liblll/CompilerState.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file CompilerState.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include - -namespace solidity::lll -{ - -struct Macro -{ - std::vector args; - boost::spirit::utree code; - std::map env; -}; - -struct CompilerState -{ - CompilerState(); - - CodeFragment const& getDef(std::string const& _s) const; - void populateStandard(); - - unsigned stackSize = 128; - std::map> vars; ///< maps name to stack offset & size. - std::map defs; - std::map args; - std::map outers; - std::map, Macro> macros; - std::vector treesToKill; - bool usedAlloc = false; -}; - -} diff --git a/liblll/Exceptions.h b/liblll/Exceptions.h deleted file mode 100644 index 57fbf6ad3..000000000 --- a/liblll/Exceptions.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file Exceptions.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include - -namespace solidity::lll -{ - -/// Compile a Low-level Lisp-like Language program into EVM-code. -class CompilerException: public util::Exception {}; -class InvalidOperation: public CompilerException {}; -class IntegerOutOfRange: public CompilerException {}; -class EmptyList: public CompilerException {}; -class DataNotExecutable: public CompilerException {}; -class IncorrectParameterCount: public CompilerException {}; -class InvalidName: public CompilerException {}; -class InvalidMacroArgs: public CompilerException {}; -class InvalidLiteral: public CompilerException {}; -class BareSymbol: public CompilerException {}; -class ParserException: public CompilerException {}; - -} diff --git a/liblll/Parser.cpp b/liblll/Parser.cpp deleted file mode 100644 index 0f8ff1053..000000000 --- a/liblll/Parser.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file Parser.cpp - * @author Gav Wood - * @date 2014 - */ - -#include - -#if _MSC_VER -#pragma warning(disable:4348) -#endif - -#define BOOST_RESULT_OF_USE_DECLTYPE -#define BOOST_SPIRIT_USE_PHOENIX_V3 -#include -#include -#include - -using namespace std; -using namespace solidity; -using namespace solidity::util; -using namespace solidity::lll; -namespace qi = boost::spirit::qi; -namespace px = boost::phoenix; -namespace sp = boost::spirit; - -void solidity::lll::killBigints(sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: for (auto const& i: _this) killBigints(i); break; - case sp::utree_type::any_type: delete _this.get(); break; - default:; - } -} - -void solidity::lll::debugOutAST(ostream& _out, sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: - switch (_this.tag()) - { - case 0: _out << "( "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << ")"; break; - case 1: _out << "@ "; debugOutAST(_out, _this.front()); break; - case 2: _out << "@@ "; debugOutAST(_out, _this.front()); break; - case 3: _out << "[ "; debugOutAST(_out, _this.front()); _out << " ] "; debugOutAST(_out, _this.back()); break; - case 4: _out << "[[ "; debugOutAST(_out, _this.front()); _out << " ]] "; debugOutAST(_out, _this.back()); break; - case 5: _out << "{ "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << "}"; break; - case 6: _out << "$ "; debugOutAST(_out, _this.front()); break; - default:; - } - - break; - case sp::utree_type::int_type: _out << _this.get(); break; - case sp::utree_type::string_type: _out << "\"" << _this.get, sp::utree_type::string_type>>() << "\""; break; - case sp::utree_type::symbol_type: _out << _this.get, sp::utree_type::symbol_type>>(); break; - case sp::utree_type::any_type: _out << *_this.get(); break; - default: _out << "nil"; - } -} - -namespace solidity { -namespace lll { -namespace parseTreeLLL_ { - -template -struct tagNode -{ - void operator()(sp::utree& n, qi::rule::context_type& c) const - { - (boost::fusion::at_c<0>(c.attributes) = n).tag(N); - } -}; - -}}} - -void solidity::lll::parseTreeLLL(string const& _s, sp::utree& o_out) -{ - using qi::standard::space; - using qi::standard::space_type; - using solidity::lll::parseTreeLLL_::tagNode; - using symbol_type = sp::basic_string; - using it = string::const_iterator; - - qi::rule element; - qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))]; - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> +qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr[qi::_val = px::construct(px::new_(qi::_1))]; - qi::rule atom = integer[qi::_val = qi::_1] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule seq = '{' > *element > '}'; - qi::rule mload = '@' > element; - qi::rule sload = qi::lit("@@") > element; - qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; - qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; - qi::rule calldataload = qi::lit("$") > element; - qi::rule list = '(' > *element > ')'; - - qi::rule extra = sload[tagNode<2>()] | mload[tagNode<1>()] | sstore[tagNode<4>()] | mstore[tagNode<3>()] | seq[tagNode<5>()] | calldataload[tagNode<6>()]; - element = atom | list | extra; - - string s; - s.reserve(_s.size()); - bool incomment = false; - bool instring = false; - bool insstring = false; - for (auto i: _s) - { - if (i == ';' && !instring && !insstring) - incomment = true; - else if (i == '\n') - incomment = instring = insstring = false; - else if (i == '"' && !insstring) - instring = !instring; - else if (i == '\'') - insstring = true; - else if (i == ' ') - insstring = false; - if (!incomment) - s.push_back(i); - } - auto ret = s.cbegin(); - try - { - qi::phrase_parse(ret, s.cend(), element, space, qi::skip_flag::dont_postskip, o_out); - } - catch (qi::expectation_failure const& e) - { - std::string fragment(e.first, e.last); - std::string loc = to_string(std::distance(s.cbegin(), e.first) - 1); - std::string reason("Lexer failure at " + loc + ": '" + fragment + "'"); - BOOST_THROW_EXCEPTION(ParserException() << errinfo_comment(reason)); - } - for (auto i = ret; i != s.cend(); ++i) - if (!isspace(*i)) - { - BOOST_THROW_EXCEPTION(ParserException() << errinfo_comment("Non-whitespace left in parser")); - } -} diff --git a/liblll/Parser.h b/liblll/Parser.h deleted file mode 100644 index 424356e0c..000000000 --- a/liblll/Parser.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file Parser.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include -#include -#include - -namespace boost { namespace spirit { class utree; } } -namespace sp = boost::spirit; - -namespace solidity::lll -{ - -void killBigints(sp::utree const& _this); -void parseTreeLLL(std::string const& _s, sp::utree& o_out); -void debugOutAST(std::ostream& _out, sp::utree const& _this); - -} diff --git a/lllc/CMakeLists.txt b/lllc/CMakeLists.txt deleted file mode 100644 index 4e78207e2..000000000 --- a/lllc/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -add_executable(lllc main.cpp) -target_link_libraries(lllc PRIVATE lll Boost::boost Boost::system) - -if (INSTALL_LLLC) - include(GNUInstallDirs) - install(TARGETS lllc DESTINATION ${CMAKE_INSTALL_BINDIR}) - - if(LLLC_LINK_STATIC AND UNIX AND NOT APPLE) - # Produce lllc as statically linked binary (includes C/C++ standard libraries) - # This is not supported on macOS, see - # https://developer.apple.com/library/content/qa/qa1118/_index.html. - set_target_properties( - lllc PROPERTIES - LINK_FLAGS -static - LINK_SEARCH_START_STATIC ON - LINK_SEARCH_END_STATIC ON - ) - endif() -endif() diff --git a/lllc/main.cpp b/lllc/main.cpp deleted file mode 100644 index 75d193e23..000000000 --- a/lllc/main.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** @file main.cpp - * @author Gav Wood - * @date 2014 - * Ethereum client. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace solidity; -using namespace solidity::util; -using namespace solidity::lll; - -static string const VersionString = - string(ETH_PROJECT_VERSION) + - (string(SOL_VERSION_PRERELEASE).empty() ? "" : "-" + string(SOL_VERSION_PRERELEASE)) + - (string(SOL_VERSION_BUILDINFO).empty() ? "" : "+" + string(SOL_VERSION_BUILDINFO)); - -static void help() -{ - cout - << "Usage lllc [OPTIONS] " << endl - << "Options:" << endl - << " -b,--binary Parse, compile and assemble; output byte code in binary." << endl - << " -x,--hex Parse, compile and assemble; output byte code in hex." << endl - << " -a,--assembly Only parse and compile; show assembly." << endl - << " -t,--parse-tree Only parse; show parse tree." << endl - << " -o,--optimise Turn on/off the optimiser; off by default." << endl - << " -d,--disassemble Disassemble input into an opcode stream." << endl - << " -h,--help Show this help message and exit." << endl - << " -V,--version Show the version and exit." << endl; - exit(0); -} - -static void version() -{ - cout << "LLLC, the Lovely Little Language Compiler" << endl; - cout << "Version: " << VersionString << endl; - exit(0); -} - -/* -The equivalent of setlocale(LC_ALL, "C") is called before any user code is run. -If the user has an invalid environment setting then it is possible for the call -to set locale to fail, so there are only two possible actions, the first is to -throw a runtime exception and cause the program to quit (default behaviour), -or the second is to modify the environment to something sensible (least -surprising behaviour). - -The follow code produces the least surprising behaviour. It will use the user -specified default locale if it is valid, and if not then it will modify the -environment the process is running in to use a sensible default. This also means -that users do not need to install language packs for their OS. -*/ -static void setDefaultOrCLocale() -{ -#if __unix__ - if (!std::setlocale(LC_ALL, "")) - { - setenv("LC_ALL", "C", 1); - } -#endif -} - -enum Mode { Binary, Hex, Assembly, ParseTree, Disassemble }; - -int main(int argc, char** argv) -{ - setDefaultOrCLocale(); - unsigned optimise = 0; - string infile; - Mode mode = Hex; - - for (int i = 1; i < argc; ++i) - { - string arg = argv[i]; - if (arg == "-h" || arg == "--help") - help(); - else if (arg == "-b" || arg == "--binary") - mode = Binary; - else if (arg == "-x" || arg == "--hex") - mode = Hex; - else if (arg == "-a" || arg == "--assembly") - mode = Assembly; - else if (arg == "-t" || arg == "--parse-tree") - mode = ParseTree; - else if (arg == "-o" || arg == "--optimise") - optimise = 1; - else if (arg == "-d" || arg == "--disassemble") - mode = Disassemble; - else if (arg == "-V" || arg == "--version") - version(); - else - infile = argv[i]; - } - - string src; - if (infile.empty()) - src = readStandardInput(); - else - src = readFileAsString(infile); - - vector errors; - if (src.empty()) - { - errors.push_back("Empty file."); - } - else if (mode == Disassemble) - { - cout << evmasm::disassemble(fromHex(src)) << endl; - } - else if (mode == Binary || mode == Hex) - { - auto bs = compileLLL(std::move(src), langutil::EVMVersion{}, optimise ? true : false, &errors, readFileAsString); - if (mode == Hex) - cout << toHex(bs) << endl; - else if (mode == Binary) - cout.write((char const*)bs.data(), bs.size()); - } - else if (mode == ParseTree) - { - cout << parseLLL(std::move(src)) << endl; - } - else if (mode == Assembly) - { - cout << compileLLLToAsm(std::move(src), langutil::EVMVersion{}, optimise ? true : false, &errors, readFileAsString) << endl; - } - - for (auto const& i: errors) - cerr << i << endl; - if (errors.size()) - return 1; - return 0; -} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4ce4439e8..a6b753087 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -51,19 +51,6 @@ set(liblangutil_sources ) detect_stray_source_files("${liblangutil_sources}" "liblangutil/") -if(LLL) - set (liblll_sources - liblll/Compiler.cpp - liblll/EndToEndTest.cpp - liblll/ExecutionFramework.cpp - liblll/ExecutionFramework.h - liblll/LLL_ENS.cpp - liblll/LLL_ERC20.cpp - liblll/Parser.cpp - ) - detect_stray_source_files("${liblll_sources}" "liblll/") -endif(LLL) - set(libsolidity_sources libsolidity/ABIDecoderTests.cpp libsolidity/ABIEncoderTests.cpp @@ -155,7 +142,6 @@ add_executable(soltest ${sources} ${liblangutil_sources} ${libevmasm_sources} ${libyul_sources} - ${liblll_sources} ${libsolidity_sources} ${libsolidity_util_sources} ) @@ -170,11 +156,6 @@ if (MSVC) target_compile_options(soltest PUBLIC "/bigobj") endif() -if (LLL) - target_link_libraries(soltest PRIVATE lll) - target_compile_definitions(soltest PRIVATE HAVE_LLL=1) -endif() - if (NOT Boost_USE_STATIC_LIBS) target_compile_definitions(soltest PUBLIC -DBOOST_TEST_DYN_LINK) endif() diff --git a/test/boostTest.cpp b/test/boostTest.cpp index edecdd0de..47b700381 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -164,11 +164,6 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "SolidityAuctionRegistrar", "SolidityFixedFeeRegistrar", "SolidityWallet", -#if HAVE_LLL - "LLLERC20", - "LLLENS", - "LLLEndToEndTest", -#endif "GasMeterTests", "GasCostTests", "SolidityEndToEndTest", diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp deleted file mode 100644 index 3c60e7ee9..000000000 --- a/test/liblll/Compiler.cpp +++ /dev/null @@ -1,670 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @author Alex Beregszaszi - * @date 2017 - * Unit tests for the LLL compiler. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace solidity::util; - -namespace solidity::lll::test -{ - -namespace -{ - -bool successCompile(string const& _sourceCode) -{ - vector errors; - bytes bytecode = lll::compileLLL(_sourceCode, solidity::test::Options::get().evmVersion(), false, &errors); - if (!errors.empty()) - return false; - if (bytecode.empty()) - return false; - return true; -} - -} - -BOOST_AUTO_TEST_SUITE(LLLCompiler) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - char const* sourceCode = "1"; - BOOST_CHECK(successCompile(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(switch_valid) -{ - char const* sourceCode = R"( - (switch (origin)) - )"; - BOOST_CHECK(successCompile(sourceCode)); - sourceCode = R"( - (switch - 1 (panic) - 2 (panic)) - )"; - BOOST_CHECK(successCompile(sourceCode)); - sourceCode = R"( - (switch - 1 (panic) - 2 (panic) - (panic)) - )"; - BOOST_CHECK(successCompile(sourceCode)); - sourceCode = R"( - (switch - 1 (origin) - 2 (origin) - (origin)) - )"; - BOOST_CHECK(successCompile(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(switch_invalid_arg_count) -{ - char const* sourceCode = R"( - (switch) - )"; - BOOST_CHECK(!successCompile(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(switch_inconsistent_return_count) -{ - // cannot return stack items if the default case is not present - char const* sourceCode = R"( - (switch - 1 (origin) - 2 (origin) - )"; - BOOST_CHECK(!successCompile(sourceCode)); - // return count mismatch - sourceCode = R"( - (switch - 1 (origin) - 2 (origin) - (panic)) - )"; - BOOST_CHECK(!successCompile(sourceCode)); - // return count mismatch - sourceCode = R"( - (switch - 1 (panic) - 2 (panic) - (origin)) - )"; - BOOST_CHECK(!successCompile(sourceCode)); -} - -BOOST_AUTO_TEST_CASE(disallowed_asm_instructions) -{ - for (unsigned i = 1; i <= 32; i++) - BOOST_CHECK(!successCompile("(asm PUSH" + to_string(i) + ")")); -} - -BOOST_AUTO_TEST_CASE(disallowed_functional_asm_instructions) -{ - for (unsigned i = 1; i <= 32; i++) - BOOST_CHECK(!successCompile("(PUSH" + to_string(i) + ")")); - for (unsigned i = 1; i <= 16; i++) - BOOST_CHECK(!successCompile("(DUP" + to_string(i) + ")")); - for (unsigned i = 1; i <= 16; i++) - BOOST_CHECK(!successCompile("(SWAP" + to_string(i) + ")")); - BOOST_CHECK(!successCompile("(JUMPDEST)")); -} - -BOOST_AUTO_TEST_CASE(valid_opcodes_functional) -{ - vector opcodes_bytecode { - "0000", - "600060000100", - "600060000200", - "600060000300", - "600060000400", - "600060000500", - "600060000600", - "600060000700", - "6000600060000800", - "6000600060000900", - "600060000a00", - "600060000b00", - "600060001000", - "600060001100", - "600060001200", - "600060001300", - "600060001400", - "60001500", - "600060001600", - "600060001700", - "600060001800", - "60001900", - "600060001a00", - "600060002000", - "3000", - "60003100", - "3200", - "3300", - "3400", - "60003500", - "3600", - "6000600060003700", - "3800", - "6000600060003900", - "3a00", - "60003b00", - "60006000600060003c00", - "3d00", - "6000600060003e00", - "60003f00", - "60004000", - "4100", - "4200", - "4300", - "4400", - "4500", - "4600", - "4700", - "60005000", - "60005100", - "600060005200", - "600060005300", - "60005400", - "600060005500", - "60005600", - "600060005700", - "5800", - "5900", - "5a00", - "60ff00", - "61ffff00", - "62ffffff00", - "63ffffffff00", - "64ffffffffff00", - "65ffffffffffff00", - "66ffffffffffffff00", - "67ffffffffffffffff00", - "68ffffffffffffffffff00", - "69ffffffffffffffffffff00", - "6affffffffffffffffffffff00", - "6bffffffffffffffffffffffff00", - "6cffffffffffffffffffffffffff00", - "6dffffffffffffffffffffffffffff00", - "6effffffffffffffffffffffffffffff00", - "6fffffffffffffffffffffffffffffffff00", - "70ffffffffffffffffffffffffffffffffff00", - "71ffffffffffffffffffffffffffffffffffff00", - "72ffffffffffffffffffffffffffffffffffffff00", - "73ffffffffffffffffffffffffffffffffffffffff00", - "74ffffffffffffffffffffffffffffffffffffffffff00", - "75ffffffffffffffffffffffffffffffffffffffffffff00", - "76ffffffffffffffffffffffffffffffffffffffffffffff00", - "77ffffffffffffffffffffffffffffffffffffffffffffffff00", - "78ffffffffffffffffffffffffffffffffffffffffffffffffff00", - "79ffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7affffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "60006000a000", - "600060006000a100", - "6000600060006000a200", - "60006000600060006000a300", - "600060006000600060006000a400", - "600060006000f000", - "6000600060006000600060006000f100", - "6000600060006000600060006000f200", - "60006000f300", - "600060006000600060006000f400", - "600060006000600060006000fa00", - "60006000fd00", - "fe00", - "6000ff00" - }; - - vector opcodes_lll { - "(STOP)", - "(ADD 0 0)", - "(MUL 0 0)", - "(SUB 0 0)", - "(DIV 0 0)", - "(SDIV 0 0)", - "(MOD 0 0)", - "(SMOD 0 0)", - "(ADDMOD 0 0 0)", - "(MULMOD 0 0 0)", - "(EXP 0 0)", - "(SIGNEXTEND 0 0)", - "(LT 0 0)", - "(GT 0 0)", - "(SLT 0 0)", - "(SGT 0 0)", - "(EQ 0 0)", - "(ISZERO 0)", - "(AND 0 0)", - "(OR 0 0)", - "(XOR 0 0)", - "(NOT 0)", - "(BYTE 0 0)", - "(KECCAK256 0 0)", - "(ADDRESS)", - "(BALANCE 0)", - "(ORIGIN)", - "(CALLER)", - "(CALLVALUE)", - "(CALLDATALOAD 0)", - "(CALLDATASIZE)", - "(CALLDATACOPY 0 0 0)", - "(CODESIZE)", - "(CODECOPY 0 0 0)", - "(GASPRICE)", - "(EXTCODESIZE 0)", - "(EXTCODECOPY 0 0 0 0)", - "(RETURNDATASIZE)", - "(RETURNDATACOPY 0 0 0)", - "(EXTCODEHASH 0)", - "(BLOCKHASH 0)", - "(COINBASE)", - "(TIMESTAMP)", - "(NUMBER)", - "(DIFFICULTY)", - "(GASLIMIT)", - "(CHAINID)", - "(SELFBALANCE)", - "(POP 0)", - "(MLOAD 0)", - "(MSTORE 0 0)", - "(MSTORE8 0 0)", - "(SLOAD 0)", - "(SSTORE 0 0)", - "(JUMP 0)", - "(JUMPI 0 0)", - "(PC)", - "(MSIZE)", - "(GAS)", - "0xff", - "0xffff", - "0xffffff", - "0xffffffff", - "0xffffffffff", - "0xffffffffffff", - "0xffffffffffffff", - "0xffffffffffffffff", - "0xffffffffffffffffff", - "0xffffffffffffffffffff", - "0xffffffffffffffffffffff", - "0xffffffffffffffffffffffff", - "0xffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "(LOG0 0 0)", - "(LOG1 0 0 0)", - "(LOG2 0 0 0 0)", - "(LOG3 0 0 0 0 0)", - "(LOG4 0 0 0 0 0 0)", - "(CREATE 0 0 0)", - "(CALL 0 0 0 0 0 0 0)", - "(CALLCODE 0 0 0 0 0 0 0)", - "(RETURN 0 0)", - "(DELEGATECALL 0 0 0 0 0 0)", - "(STATICCALL 0 0 0 0 0 0)", - "(REVERT 0 0)", - "(INVALID)", - "(SELFDESTRUCT 0)" - }; - - for (size_t i = 0; i < opcodes_bytecode.size(); i++) - { - vector errors; - bytes code = lll::compileLLL(opcodes_lll[i], solidity::test::Options::get().evmVersion(), false, &errors); - - BOOST_REQUIRE_MESSAGE(errors.empty(), opcodes_lll[i]); - - BOOST_CHECK_EQUAL(toHex(code), opcodes_bytecode[i]); - } -} - -BOOST_AUTO_TEST_CASE(valid_opcodes_asm) -{ - vector opcodes_bytecode { - "0000", - "600060000100", - "600060000200", - "600060000300", - "600060000400", - "600060000500", - "600060000600", - "600060000700", - "6000600060000800", - "6000600060000900", - "600060000a00", - "600060000b00", - "600060001000", - "600060001100", - "600060001200", - "600060001300", - "600060001400", - "60001500", - "600060001600", - "600060001700", - "600060001800", - "60001900", - "600060001a00", - "600060002000", - "3000", - "60003100", - "3200", - "3300", - "3400", - "60003500", - "3600", - "6000600060003700", - "3800", - "6000600060003900", - "3a00", - "60003b00", - "60006000600060003c00", - "3d00", - "6000600060003e00", - "60003f00", - "4000", - "4100", - "4200", - "4300", - "4400", - "4500", - "4600", - "4700", - "60005000", - "60005100", - "600060005200", - "600060005300", - "60005400", - "600060005500", - "60005600", - "600060005700", - "5800", - "5900", - "5a00", - "5b00", - "60ff00", - "61ffff00", - "62ffffff00", - "63ffffffff00", - "64ffffffffff00", - "65ffffffffffff00", - "66ffffffffffffff00", - "67ffffffffffffffff00", - "68ffffffffffffffffff00", - "69ffffffffffffffffffff00", - "6affffffffffffffffffffff00", - "6bffffffffffffffffffffffff00", - "6cffffffffffffffffffffffffff00", - "6dffffffffffffffffffffffffffff00", - "6effffffffffffffffffffffffffffff00", - "6fffffffffffffffffffffffffffffffff00", - "70ffffffffffffffffffffffffffffffffff00", - "71ffffffffffffffffffffffffffffffffffff00", - "72ffffffffffffffffffffffffffffffffffffff00", - "73ffffffffffffffffffffffffffffffffffffffff00", - "74ffffffffffffffffffffffffffffffffffffffffff00", - "75ffffffffffffffffffffffffffffffffffffffffffff00", - "76ffffffffffffffffffffffffffffffffffffffffffffff00", - "77ffffffffffffffffffffffffffffffffffffffffffffffff00", - "78ffffffffffffffffffffffffffffffffffffffffffffffffff00", - "79ffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7affffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00", - "60006000600060006000600060006000600060006000600060006000600060008000", - "60006000600060006000600060006000600060006000600060006000600060008100", - "60006000600060006000600060006000600060006000600060006000600060008200", - "60006000600060006000600060006000600060006000600060006000600060008300", - "60006000600060006000600060006000600060006000600060006000600060008400", - "60006000600060006000600060006000600060006000600060006000600060008500", - "60006000600060006000600060006000600060006000600060006000600060008600", - "60006000600060006000600060006000600060006000600060006000600060008700", - "60006000600060006000600060006000600060006000600060006000600060008800", - "60006000600060006000600060006000600060006000600060006000600060008900", - "60006000600060006000600060006000600060006000600060006000600060008a00", - "60006000600060006000600060006000600060006000600060006000600060008b00", - "60006000600060006000600060006000600060006000600060006000600060008c00", - "60006000600060006000600060006000600060006000600060006000600060008d00", - "60006000600060006000600060006000600060006000600060006000600060008e00", - "60006000600060006000600060006000600060006000600060006000600060008f00", - "60006000600060006000600060006000600060006000600060006000600060009000", - "60006000600060006000600060006000600060006000600060006000600060009100", - "60006000600060006000600060006000600060006000600060006000600060009200", - "60006000600060006000600060006000600060006000600060006000600060009300", - "60006000600060006000600060006000600060006000600060006000600060009400", - "60006000600060006000600060006000600060006000600060006000600060009500", - "60006000600060006000600060006000600060006000600060006000600060009600", - "60006000600060006000600060006000600060006000600060006000600060009700", - "60006000600060006000600060006000600060006000600060006000600060009800", - "60006000600060006000600060006000600060006000600060006000600060009900", - "60006000600060006000600060006000600060006000600060006000600060009a00", - "60006000600060006000600060006000600060006000600060006000600060009b00", - "60006000600060006000600060006000600060006000600060006000600060009c00", - "60006000600060006000600060006000600060006000600060006000600060009d00", - "60006000600060006000600060006000600060006000600060006000600060009e00", - "60006000600060006000600060006000600060006000600060006000600060009f00", - "60006000a000", - "600060006000a100", - "6000600060006000a200", - "60006000600060006000a300", - "600060006000600060006000a400", - "600060006000f000", - "600060006000600060006000f100", - "600060006000600060006000f200", - "60006000f300", - "60006000600060006000f400", - "60006000600060006000fa00", - "60006000fd00", - "fe00", - "6000ff00" - }; - - vector opcodes_lll { - "(asm STOP)", - "(asm 0 0 ADD)", - "(asm 0 0 MUL)", - "(asm 0 0 SUB)", - "(asm 0 0 DIV)", - "(asm 0 0 SDIV)", - "(asm 0 0 MOD)", - "(asm 0 0 SMOD)", - "(asm 0 0 0 ADDMOD)", - "(asm 0 0 0 MULMOD)", - "(asm 0 0 EXP)", - "(asm 0 0 SIGNEXTEND)", - "(asm 0 0 LT)", - "(asm 0 0 GT)", - "(asm 0 0 SLT)", - "(asm 0 0 SGT)", - "(asm 0 0 EQ)", - "(asm 0 ISZERO)", - "(asm 0 0 AND)", - "(asm 0 0 OR)", - "(asm 0 0 XOR)", - "(asm 0 NOT)", - "(asm 0 0 BYTE)", - "(asm 0 0 KECCAK256)", - "(asm ADDRESS)", - "(asm 0 BALANCE)", - "(asm ORIGIN)", - "(asm CALLER)", - "(asm CALLVALUE)", - "(asm 0 CALLDATALOAD)", - "(asm CALLDATASIZE)", - "(asm 0 0 0 CALLDATACOPY)", - "(asm CODESIZE)", - "(asm 0 0 0 CODECOPY)", - "(asm GASPRICE)", - "(asm 0 EXTCODESIZE)", - "(asm 0 0 0 0 EXTCODECOPY)", - "(asm RETURNDATASIZE)", - "(asm 0 0 0 RETURNDATACOPY)", - "(asm 0 EXTCODEHASH)", - "(asm BLOCKHASH)", - "(asm COINBASE)", - "(asm TIMESTAMP)", - "(asm NUMBER)", - "(asm DIFFICULTY)", - "(asm GASLIMIT)", - "(asm CHAINID)", - "(asm SELFBALANCE)", - "(asm 0 POP)", - "(asm 0 MLOAD)", - "(asm 0 0 MSTORE)", - "(asm 0 0 MSTORE8)", - "(asm 0 SLOAD)", - "(asm 0 0 SSTORE)", - "(asm 0 JUMP)", - "(asm 0 0 JUMPI)", - "(asm PC)", - "(asm MSIZE)", - "(asm GAS)", - "(asm JUMPDEST)", - "(asm 0xff)", - "(asm 0xffff)", - "(asm 0xffffff)", - "(asm 0xffffffff)", - "(asm 0xffffffffff)", - "(asm 0xffffffffffff)", - "(asm 0xffffffffffffff)", - "(asm 0xffffffffffffffff)", - "(asm 0xffffffffffffffffff)", - "(asm 0xffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP1)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP2)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP3)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP4)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP5)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP6)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP7)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP8)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP9)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP10)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP11)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP12)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP13)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP14)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP15)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DUP16)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP1)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP2)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP3)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP4)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP5)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP6)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP7)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP8)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP9)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP10)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP11)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP12)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP13)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP14)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP15)", - "(asm 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SWAP16)", - "(asm 0 0 LOG0)", - "(asm 0 0 0 LOG1)", - "(asm 0 0 0 0 LOG2)", - "(asm 0 0 0 0 0 LOG3)", - "(asm 0 0 0 0 0 0 LOG4)", - "(asm 0 0 0 CREATE)", - "(asm 0 0 0 0 0 0 CALL)", - "(asm 0 0 0 0 0 0 CALLCODE)", - "(asm 0 0 RETURN)", - "(asm 0 0 0 0 0 DELEGATECALL)", - "(asm 0 0 0 0 0 STATICCALL)", - "(asm 0 0 REVERT)", - "(asm INVALID)", - "(asm 0 SELFDESTRUCT)" - }; - - for (size_t i = 0; i < opcodes_bytecode.size(); i++) - { - vector errors; - bytes code = lll::compileLLL(opcodes_lll[i], solidity::test::Options::get().evmVersion(), false, &errors); - - BOOST_REQUIRE_MESSAGE(errors.empty(), opcodes_lll[i]); - - BOOST_CHECK_EQUAL(toHex(code), opcodes_bytecode[i]); - } -} - -BOOST_AUTO_TEST_SUITE_END() - -} // end namespaces diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp deleted file mode 100644 index cadfae757..000000000 --- a/test/liblll/EndToEndTest.cpp +++ /dev/null @@ -1,1026 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @author Alex Beregszaszi - * @date 2016 - * End to end tests for LLL. - */ - -#include -#include - -#include - -#include -#include - -using namespace std; -using namespace solidity::util; -using namespace solidity::test; - -namespace solidity::lll::test -{ - -BOOST_FIXTURE_TEST_SUITE(LLLEndToEndTest, LLLExecutionFramework) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - char const* sourceCode = "(returnlll { (return \"test\") })"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(string("test", 4))); -} - -BOOST_AUTO_TEST_CASE(bare_panic) -{ - char const* sourceCode = "(panic)"; - compileAndRunWithoutCheck(sourceCode); - BOOST_REQUIRE(!m_transactionSuccessful); - BOOST_REQUIRE(m_output.empty()); -} - -BOOST_AUTO_TEST_CASE(panic) -{ - char const* sourceCode = "{ (panic) }"; - compileAndRunWithoutCheck(sourceCode); - BOOST_REQUIRE(!m_transactionSuccessful); - BOOST_REQUIRE(m_output.empty()); -} - -BOOST_AUTO_TEST_CASE(macro_zeroarg) -{ - char const* sourceCode = R"( - (returnlll - (seq - (def 'zeroarg () (seq (mstore 0 0x1234) (return 0 32))) - (zeroarg))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(m_transactionSuccessful); - BOOST_CHECK(callFallback() == encodeArgs(u256(0x1234))); -} - -BOOST_AUTO_TEST_CASE(macros) -{ - char const* sourceCode = R"( - (returnlll - (seq - (def 'x 1) - (def 'y () { (def 'x (+ x 2)) }) - (y) - (return x))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(3))); -} - -BOOST_AUTO_TEST_CASE(variables) -{ - char const* sourceCode = R"( - (returnlll - (seq - (set 'x 1) - (set 'y 2) - ;; this should equal to 3 - (set 'z (add (get 'x) (get 'y))) - ;; overwriting it here - (set 'y 4) - ;; each variable has a 32 byte slot, starting from memory location 0x80 - ;; variable addresses can also be retrieved by x or (ref 'x) - (set 'k (add (add (ref 'x) (ref 'y)) z)) - (return (add (add (get 'x) (add (get 'y) (get 'z))) (get 'k))))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(488))); -} - -BOOST_AUTO_TEST_CASE(with) -{ - char const* sourceCode = R"( - (returnlll - (seq - (set 'x 11) - (with 'y 22 { [0]:(+ (get 'x) (get 'y)) }) - (return 0 32))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == toBigEndian(u256(33))); -} - -BOOST_AUTO_TEST_CASE(when) -{ - char const* sourceCode = R"( - (returnlll - (seq - (when (= (calldatasize) 0) (return 1)) - (when (!= (calldatasize) 0) (return 2)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); - BOOST_CHECK(callFallback() == toBigEndian(u256(1))); -} - -BOOST_AUTO_TEST_CASE(unless) -{ - char const* sourceCode = R"( - (returnlll - (seq - (unless (!= (calldatasize) 0) (return 1)) - (unless (= (calldatasize) 0) (return 2)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); - BOOST_CHECK(callFallback() == toBigEndian(u256(1))); -} - -BOOST_AUTO_TEST_CASE(conditional_literal) -{ - char const* sourceCode = R"( - (returnlll - (seq - (return (if (= (calldatasize) 0) 1 2)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); - BOOST_CHECK(callFallback() == toBigEndian(u256(1))); -} - -BOOST_AUTO_TEST_CASE(conditional) -{ - char const* sourceCode = R"( - (returnlll - (seq - (if (= (calldatasize) 0) (return 1) (return 2)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); - BOOST_CHECK(callFallback() == toBigEndian(u256(1))); -} - -BOOST_AUTO_TEST_CASE(conditional_seq) -{ - char const* sourceCode = R"( - (returnlll - (seq - (return (if (= (calldatasize) 0) { 0 2 1 } { 0 1 2 })))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(2))); - BOOST_CHECK(callFallback() == toBigEndian(u256(1))); -} - -BOOST_AUTO_TEST_CASE(conditional_nested_else) -{ - char const* sourceCode = R"( - (returnlll - (seq - (def 'input (calldataload 0x04)) - ;; Calculates width in bytes of utf-8 characters. - (return - (if (< input 0x80) 1 - (if (< input 0xE0) 2 - (if (< input 0xF0) 3 - (if (< input 0xF8) 4 - (if (< input 0xFC) 5 - 6)))))))) - - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()", 0x00) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("test()", 0x80) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("test()", 0xe0) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("test()", 0xf0) == encodeArgs(u256(4))); - BOOST_CHECK(callContractFunction("test()", 0xf8) == encodeArgs(u256(5))); - BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); -} - -BOOST_AUTO_TEST_CASE(conditional_nested_then) -{ - char const* sourceCode = R"( - (returnlll - (seq - (def 'input (calldataload 0x04)) - ;; Calculates width in bytes of utf-8 characters. - (return - (if (>= input 0x80) - (if (>= input 0xE0) - (if (>= input 0xF0) - (if (>= input 0xF8) - (if (>= input 0xFC) - 6 5) 4) 3) 2) 1)))) - - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()", 0x00) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("test()", 0x80) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("test()", 0xe0) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("test()", 0xf0) == encodeArgs(u256(4))); - BOOST_CHECK(callContractFunction("test()", 0xf8) == encodeArgs(u256(5))); - BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); -} - -BOOST_AUTO_TEST_CASE(conditional_switch) -{ - char const* sourceCode = R"( - (returnlll - (seq - (def 'input (calldataload 0x04)) - ;; Calculates width in bytes of utf-8 characters. - (return - (switch - (< input 0x80) 1 - (< input 0xE0) 2 - (< input 0xF0) 3 - (< input 0xF8) 4 - (< input 0xFC) 5 - 6)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()", 0x00) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("test()", 0x80) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("test()", 0xe0) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("test()", 0xf0) == encodeArgs(u256(4))); - BOOST_CHECK(callContractFunction("test()", 0xf8) == encodeArgs(u256(5))); - BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6))); -} - -BOOST_AUTO_TEST_CASE(conditional_switch_one_arg_with_deposit) -{ - char const* sourceCode = R"( - (returnlll - (return - (switch 42))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(42))); -} - -BOOST_AUTO_TEST_CASE(conditional_switch_one_arg_no_deposit) -{ - char const* sourceCode = R"( - (returnlll - (seq - (switch [0]:42) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(42))); -} - -BOOST_AUTO_TEST_CASE(conditional_switch_two_args) -{ - char const* sourceCode = R"( - (returnlll - (seq - (switch (= (calldataload 0x04) 1) [0]:42) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(42))); -} - -BOOST_AUTO_TEST_CASE(conditional_switch_three_args_with_deposit) -{ - char const* sourceCode = R"( - (returnlll - (return - (switch (= (calldataload 0x04) 1) 41 42))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(42))); - BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(41))); -} - -BOOST_AUTO_TEST_CASE(conditional_switch_three_args_no_deposit) -{ - char const* sourceCode = R"( - (returnlll - (switch - (= (calldataload 0x04) 1) (return 41) - (return 42))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(42))); - BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(41))); -} - -BOOST_AUTO_TEST_CASE(exp_operator_const) -{ - char const* sourceCode = R"( - (returnlll - (return (exp 2 3))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == toBigEndian(u256(8))); -} - -BOOST_AUTO_TEST_CASE(exp_operator_const_signed) -{ - char const* sourceCode = R"( - (returnlll - (return (exp (- 0 2) 3))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == toBigEndian(u256(-8))); -} - -BOOST_AUTO_TEST_CASE(exp_operator_on_range) -{ - char const* sourceCode = R"( - (returnlll - (seq - (when (= (div (calldataload 0x00) (exp 2 224)) 0xb3de648b) - (return (exp 2 (calldataload 0x04)))) - (jump 0x02))) - )"; - compileAndRun(sourceCode); - testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to()); }, 0, 16); -} - -BOOST_AUTO_TEST_CASE(constructor_argument_internal_numeric) -{ - char const* sourceCode = R"( - (seq - (sstore 0x00 65535) - (returnlll - (return @@0x00))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(65535))); -} - -BOOST_AUTO_TEST_CASE(constructor_argument_internal_string) -{ - char const* sourceCode = R"( - (seq - (sstore 0x00 "test") - (returnlll - (return @@0x00))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs("test")); -} - -BOOST_AUTO_TEST_CASE(constructor_arguments_external) -{ - char const* sourceCode = R"( - (seq - (codecopy 0x00 (bytecodesize) 64) - (sstore 0x00 @0x00) - (sstore 0x01 @0x20) - (returnlll - (seq - (when (= (div (calldataload 0x00) (exp 2 224)) 0xf2c9ecd8) - (return @@0x00)) - (when (= (div (calldataload 0x00) (exp 2 224)) 0x89ea642f) - (return @@0x01))))) - )"; - compileAndRun(sourceCode, 0, "", encodeArgs(u256(65535), "test")); - BOOST_CHECK(callContractFunction("getNumber()") == encodeArgs(u256(65535))); - BOOST_CHECK(callContractFunction("getString()") == encodeArgs("test")); -} - -BOOST_AUTO_TEST_CASE(fallback_and_invalid_function) -{ - char const* sourceCode = R"( - (returnlll - (seq - (when (= (div (calldataload 0x00) (exp 2 224)) 0xab5ed150) - (return "one")) - (when (= (div (calldataload 0x00) (exp 2 224)) 0xee784123) - (return "two")) - (return "three"))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("getOne()") == encodeArgs("one")); - BOOST_CHECK(callContractFunction("getTwo()") == encodeArgs("two")); - BOOST_CHECK(callContractFunction("invalidFunction()") == encodeArgs("three")); - BOOST_CHECK(callFallback() == encodeArgs("three")); -} - -BOOST_AUTO_TEST_CASE(lit_string) -{ - char const* sourceCode = R"( - (returnlll - (seq - (lit 0x00 "abcdef") - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(string("abcdef"))); -} - -BOOST_AUTO_TEST_CASE(arithmetic) -{ - char const* sourceCode = R"( - (returnlll - (seq - (mstore8 0x00 (+ 160 22)) - (mstore8 0x01 (- 223 41)) - (mstore8 0x02 (* 33 2)) - (mstore8 0x03 (/ 10 2)) - (mstore8 0x04 (% 67 2)) - (mstore8 0x05 (& 15 8)) - (mstore8 0x06 (| 18 8)) - (mstore8 0x07 (^ 26 6)) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("b6b6420501081a1c000000000000000000000000000000000000000000000000"))); -} - -BOOST_AUTO_TEST_CASE(binary) -{ - char const* sourceCode = R"( - (returnlll - (seq - (mstore8 0x00 (< 53 87)) - (mstore8 0x01 (< 73 42)) - (mstore8 0x02 (<= 37 94)) - (mstore8 0x03 (<= 37 37)) - (mstore8 0x04 (<= 183 34)) - (mstore8 0x05 (S< (- 0 53) 87)) - (mstore8 0x06 (S< 73 (- 0 42))) - (mstore8 0x07 (S<= (- 0 37) 94)) - (mstore8 0x08 (S<= (- 0 37) (- 0 37))) - (mstore8 0x09 (S<= 183 (- 0 34))) - (mstore8 0x0a (> 73 42)) - (mstore8 0x0b (> 53 87)) - (mstore8 0x0c (>= 94 37)) - (mstore8 0x0d (>= 94 94)) - (mstore8 0x0e (>= 34 183)) - (mstore8 0x0f (S> 73 (- 0 42))) - (mstore8 0x10 (S> (- 0 53) 87)) - (mstore8 0x11 (S>= 94 (- 0 37))) - (mstore8 0x12 (S>= (- 0 94) (- 0 94))) - (mstore8 0x13 (S>= (- 0 34) 183)) - (mstore8 0x14 (= 53 53)) - (mstore8 0x15 (= 73 42)) - (mstore8 0x16 (!= 37 94)) - (mstore8 0x17 (!= 37 37)) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0100010100010001010001000101000100010100010001000000000000000000"))); -} - -BOOST_AUTO_TEST_CASE(unary) -{ - char const* sourceCode = R"( - (returnlll - (seq - (mstore8 0x00 (! (< 53 87))) - (mstore8 0x01 (! (>= 42 73))) - (mstore8 0x02 (~ 0x7f)) - (mstore8 0x03 (~ 0xaa)) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0001805500000000000000000000000000000000000000000000000000000000"))); -} - -BOOST_AUTO_TEST_CASE(assembly_mload_mstore) -{ - char const* sourceCode = R"( - (returnlll - (asm - 0x07 0x00 mstore - "abcdef" 0x20 mstore - 0x00 mload 0x40 mstore - 0x20 mload 0x60 mstore - 0x40 0x40 return)) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(7), string("abcdef"))); -} - -BOOST_AUTO_TEST_CASE(assembly_sload_sstore) -{ - char const* sourceCode = R"( - (returnlll - (asm - 0x07 0x00 sstore - "abcdef" 0x01 sstore - 0x00 sload 0x00 mstore - 0x01 sload 0x20 mstore - 0x40 0x00 return)) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(7), string("abcdef"))); -} - -BOOST_AUTO_TEST_CASE(assembly_codecopy) -{ - char const* sourceCode = R"( - (returnlll - (seq - (lit 0x00 "abcdef") - (asm - 0x06 6 codesize sub 0x20 codecopy - 0x20 0x20 return))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(string("abcdef"))); -} - -BOOST_AUTO_TEST_CASE(for_loop) -{ - char const* sourceCode = R"( - (returnlll - (seq - (for - { (set 'i 1) (set 'j 1) } ; INIT - (<= @i 10) ; PRED - [i]:(+ @i 1) ; POST - [j]:(* @j @i)) ; BODY - (return j 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(3628800))); // 10! -} - -BOOST_AUTO_TEST_CASE(while_loop) -{ - char const* sourceCode = R"( - (returnlll - (seq - ;; Euclid's GCD algorithm - (set 'a 1071) - (set 'b 462) - (while @b - [a]:(raw @b [b]:(mod @a @b))) - (return a 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(21))); // GCD(1071,462) -} - -BOOST_AUTO_TEST_CASE(keccak256_32bytes) -{ - char const* sourceCode = R"( - (returnlll - (seq - (mstore 0x00 0x01) - (return (keccak256 0x00 0x20)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"))); -} - -// The following tests are for the built-in macros. -// Note that panic, returnlll and return_one_arg are well covered above. - -BOOST_AUTO_TEST_CASE(allgas) -{ - char const* sourceCode = R"( - (returnlll - (return (- (gas) allgas))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(16))); // == 21 - SUB - GAS -} - -BOOST_AUTO_TEST_CASE(send_two_args) -{ - // "send" does not retain enough gas to be able to pay for account creation. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (send 0xdead 42)) - )"; - compileAndRun(sourceCode); - callFallbackWithValue(42); - BOOST_CHECK(balanceAt(Address(0xdead)) == 42); - } -} - -BOOST_AUTO_TEST_CASE(send_three_args) -{ - // "send" does not retain enough gas to be able to pay for account creation. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (send allgas 0xdead 42)) - )"; - compileAndRun(sourceCode); - callFallbackWithValue(42); - BOOST_CHECK(balanceAt(Address(0xdead)) == 42); - } -} - -// Regression test for edge case that previously failed -BOOST_AUTO_TEST_CASE(alloc_zero) -{ - char const* sourceCode = R"( - (returnlll - (seq - (mstore 0x00 (~ 0)) - (alloc 0) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(-1))); -} - -BOOST_AUTO_TEST_CASE(alloc_size) -{ - char const* sourceCode = R"( - (returnlll - (seq - (mstore 0x00 0) ; reserve space for the result of the alloc - (mstore 0x00 (alloc (calldataload 0x04))) - (return (- (msize) (mload 0x00))))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("test()", 0) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("test()", 1) == encodeArgs(u256(32))); - BOOST_CHECK(callContractFunction("test()", 32) == encodeArgs(u256(32))); - BOOST_CHECK(callContractFunction("test()", 33) == encodeArgs(u256(64))); -} - -BOOST_AUTO_TEST_CASE(alloc_start) -{ - char const* sourceCode = R"( - (returnlll - (seq - (mstore 0x40 0) ; Set initial MSIZE to 0x60 - (return (alloc 1)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(96)); -} - -BOOST_AUTO_TEST_CASE(alloc_with_variable) -{ - char const* sourceCode = R"( - (returnlll - (seq - (set 'x (alloc 1)) - (mstore8 @x 42) ; ASCII '*' - (return @x 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs("*")); -} - -BOOST_AUTO_TEST_CASE(msg_six_args) -{ - char const* sourceCode = R"( - (returnlll - (seq - (when (= 0 (calldatasize)) - (seq - (mstore 0x40 1) - (def 'outsize 0x20) - (return (msg 1000 (address) 42 0x40 0x20 outsize) outsize))) - (when (= 1 (calldataload 0x00)) - (return (callvalue))))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); -} - -BOOST_AUTO_TEST_CASE(msg_five_args) -{ - char const* sourceCode = R"( - (returnlll - (seq - (when (= 0 (calldatasize)) - (seq - (mstore 0x20 1) - (mstore 0x40 2) - (return (msg 1000 (address) 42 0x20 0x40)))) - (when (= 3 (+ (calldataload 0x00) (calldataload 0x20))) - (return (callvalue))))) - - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); -} - -BOOST_AUTO_TEST_CASE(msg_four_args) -{ - char const* sourceCode = R"( - (returnlll - (seq - (when (= 0 (calldatasize)) - (return (msg 1000 (address) 42 0xff))) - (return (callvalue)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); -} - -BOOST_AUTO_TEST_CASE(msg_three_args) -{ - // "msg" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (seq - (when (= 0 (calldatasize)) - (return (msg (address) 42 0xff))) - (return (callvalue)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); - } -} - -BOOST_AUTO_TEST_CASE(msg_two_args) -{ - // "msg" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (seq - (when (= 0 (calldatasize)) - (return (msg (address) 0xff))) - (return 42))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(42))); - } -} - -BOOST_AUTO_TEST_CASE(create_one_arg) -{ - // "call" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (seq - (call allgas - (create (returnlll (return 42))) - 0 0 0 0x00 0x20) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(42))); - } -} - -BOOST_AUTO_TEST_CASE(create_two_args) -{ - // "call" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (seq - (call allgas - (create 42 (returnlll (return (balance (address))))) - 0 0 0 0x00 0x20) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallbackWithValue(42) == encodeArgs(u256(42))); - } -} - -BOOST_AUTO_TEST_CASE(sha3_two_args) -{ - char const* sourceCode = R"( - (returnlll - (seq - (mstore 0x00 0x01) - (return (sha3 0x00 0x20)))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"))); -} - -BOOST_AUTO_TEST_CASE(sha3_one_arg) -{ - char const* sourceCode = R"( - (returnlll - (return (sha3 0x01))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"))); -} - -BOOST_AUTO_TEST_CASE(sha3pair) -{ - char const* sourceCode = R"( - (returnlll - (return (sha3pair 0x01 0x02))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0"))); -} - -BOOST_AUTO_TEST_CASE(sha3trip) -{ - char const* sourceCode = R"( - (returnlll - (return (sha3trip 0x01 0x02 0x03))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0x6e0c627900b24bd432fe7b1f713f1b0744091a646a9fe4a65a18dfed21f2949c"))); -} - -BOOST_AUTO_TEST_CASE(makeperm) // Covers makeperm (implicit), permcount and perm -{ - char const* sourceCode = R"( - (returnlll - (seq - (perm 'x) (x (+ 1 x)) - (perm 'y) (y (+ 10 y)) - (when (= 2 permcount) - (return (+ x y))))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(11))); -} - -BOOST_AUTO_TEST_CASE(ecrecover) -{ - // "ecrecover" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (return - (ecrecover - ; Hash of 'hello world' - 0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad - ; v = 1 + 27 - 0x1c - ; r - 0xdebaaa0cddb321b2dcaaf846d39605de7b97e77ba6106587855b9106cb104215 - ; s - 0x61a22d94fa8b8a687ff9c911c844d1c016d1a685a9166858f9c7c1bc85128aca))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(fromHex("0x8743523d96a1b2cbe0c6909653a56da18ed484af"))); - } -} - -BOOST_AUTO_TEST_CASE(sha256_two_args) -{ - // "sha256" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (seq - (lit 0x20 "abcdefghijklmnopqrstuvwxyzABCDEF") - (lit 0x40 "GHIJKLMNOPQRSTUVWXYZ0123456789?!") - (sha256 0x20 0x40) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0xcf25a9fe3d86ae228c226c81d2d8c64c687cd6dc4586d10d8e7e4e5b6706d429"))); - } -} - -BOOST_AUTO_TEST_CASE(ripemd160_two_args) -{ - // "ripemd160" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (seq - (lit 0x20 "abcdefghijklmnopqrstuvwxyzABCDEF") - (lit 0x40 "GHIJKLMNOPQRSTUVWXYZ0123456789?!") - (ripemd160 0x20 0x40) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0x36c6b90a49e17d4c1e1b0e634ec74124d9b207da"))); - } -} - -BOOST_AUTO_TEST_CASE(sha256_one_arg) -{ - // "sha256" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (seq - (sha256 0x6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0xcfd2f1fad75a1978da0a444883db7251414b139f31f5a04704c291fdb0e175e6"))); - } -} - -BOOST_AUTO_TEST_CASE(ripemd160_one_arg) -{ - // "ripemd160" does not retain enough gas. - // Disabling for non-tangerineWhistle VMs. - if (solidity::test::Options::get().evmVersion().canOverchargeGasForCall()) - { - char const* sourceCode = R"( - (returnlll - (seq - (ripemd160 0x6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546) - (return 0x00 0x20))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs( - fromHex("0xac5ab22e07b0fb80c69b6207902f725e2507e546"))); - } -} - -BOOST_AUTO_TEST_CASE(wei_szabo_finney_ether) -{ - char const* sourceCode = R"( - (returnlll - (return (+ wei (+ szabo (+ finney ether))))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(1001001000000000001))); -} - -BOOST_AUTO_TEST_CASE(shift_left) -{ - char const* sourceCode = R"( - (returnlll - (return (shl 1 8))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(256))); -} - -BOOST_AUTO_TEST_CASE(shift_right) -{ - char const* sourceCode = R"( - (returnlll - (return (shr 65536 8))) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256(256))); -} - -BOOST_AUTO_TEST_CASE(sub_assemblies) -{ - char const* sourceCode = R"( - (returnlll - (return (create 0 (returnlll (sstore 1 1))))) - )"; - compileAndRun(sourceCode); - bytes ret = callFallback(); - BOOST_REQUIRE(ret.size() == 32); - u256 rVal = u256(toHex(ret, HexPrefix::Add)); - BOOST_CHECK(rVal != 0); - BOOST_CHECK(rVal < u256("0x10000000000000000000000000000000000000000")); -} - -BOOST_AUTO_TEST_CASE(string_literal) -{ - char const* sourceCode = R"( - (returnlll - (return "hello")) - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == encodeArgs(u256("0x68656c6c6f000000000000000000000000000000000000000000000000000000"))); -} - -BOOST_AUTO_TEST_SUITE_END() - -} // end namespaces diff --git a/test/liblll/ExecutionFramework.cpp b/test/liblll/ExecutionFramework.cpp deleted file mode 100644 index 8f2cec672..000000000 --- a/test/liblll/ExecutionFramework.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @author Alex Beregszaszi - * @date 2016 - * Framework for executing LLL contracts and testing them via RPC. - */ - -#include -#include -#include - -using namespace solidity::test; -using namespace solidity::lll::test; - -LLLExecutionFramework::LLLExecutionFramework() : - ExecutionFramework() -{ -} diff --git a/test/liblll/ExecutionFramework.h b/test/liblll/ExecutionFramework.h deleted file mode 100644 index 1fc14f528..000000000 --- a/test/liblll/ExecutionFramework.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @author Alex Beregszaszi - * @date 2016 - * Framework for executing LLL contracts and testing them via RPC. - */ - -#pragma once - - -#include - -#include - -#include - -namespace solidity::lll::test -{ - -class LLLExecutionFramework: public solidity::test::ExecutionFramework -{ -public: - LLLExecutionFramework(); - - virtual bytes const& compileAndRunWithoutCheck( - std::string const& _sourceCode, - u256 const& _value = 0, - std::string const& _contractName = "", - bytes const& _arguments = bytes(), - std::map const& _libraryAddresses = {} - ) override - { - BOOST_REQUIRE(_contractName.empty()); - BOOST_REQUIRE(_libraryAddresses.empty()); - - std::vector errors; - bytes bytecode = lll::compileLLL( - _sourceCode, - solidity::test::Options::get().evmVersion(), - m_optimiserSettings == solidity::frontend::OptimiserSettings::standard(), - &errors - ); - if (!errors.empty()) - { - for (auto const& error: errors) - std::cerr << error << std::endl; - BOOST_ERROR("Compiling contract failed"); - } - sendMessage(bytecode + _arguments, true, _value); - return m_output; - } -}; - -} // end namespaces diff --git a/test/liblll/LLL_ENS.cpp b/test/liblll/LLL_ENS.cpp deleted file mode 100644 index 51d303b82..000000000 --- a/test/liblll/LLL_ENS.cpp +++ /dev/null @@ -1,503 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @author Ben Edgington - * @date 2017 - * Tests for the deployed ENS Registry implementation written in LLL - */ - -#include -#include -#include -#include - -#define ACCOUNT(n) h256(account(n), h256::AlignRight) - -using namespace std; -using namespace solidity::lll; -using namespace solidity::util; -using namespace solidity::test; - -namespace solidity::lll::test -{ - -namespace -{ - -static char const* ensCode = R"DELIMITER( -;;; --------------------------------------------------------------------------- -;;; @title The Ethereum Name Service registry. -;;; @author Daniel Ellison - -(seq - - ;; -------------------------------------------------------------------------- - ;; Constant definitions. - - ;; Memory layout. - (def 'node-bytes 0x00) - (def 'label-bytes 0x20) - (def 'call-result 0x40) - - ;; Struct: Record - (def 'resolver 0x00) ; address - (def 'owner 0x20) ; address - (def 'ttl 0x40) ; uint64 - - ;; Precomputed function IDs. - (def 'get-node-owner 0x02571be3) ; owner(bytes32) - (def 'get-node-resolver 0x0178b8bf) ; resolver(bytes32) - (def 'get-node-ttl 0x16a25cbd) ; ttl(bytes32) - (def 'set-node-owner 0x5b0fc9c3) ; setOwner(bytes32,address) - (def 'set-subnode-owner 0x06ab5923) ; setSubnodeOwner(bytes32,bytes32,address) - (def 'set-node-resolver 0x1896f70a) ; setResolver(bytes32,address) - (def 'set-node-ttl 0x14ab9038) ; setTTL(bytes32,uint64) - - ;; Jumping here causes an EVM error. - (def 'invalid-location 0x02) - - ;; -------------------------------------------------------------------------- - ;; @notice Shifts the leftmost 4 bytes of a 32-byte number right by 28 bytes. - ;; @param input A 32-byte number. - - (def 'shift-right (input) - (div input (exp 2 224))) - - ;; -------------------------------------------------------------------------- - ;; @notice Determines whether the supplied function ID matches a known - ;; function hash and executes if so. - ;; @dev The function ID is in the leftmost four bytes of the call data. - ;; @param function-hash The four-byte hash of a known function signature. - ;; @param code-body The code to run in the case of a match. - - (def 'function (function-hash code-body) - (when (= (shift-right (calldataload 0x00)) function-hash) - code-body)) - - ;; -------------------------------------------------------------------------- - ;; @notice Calculates record location for the node and label passed in. - ;; @param node The parent node. - ;; @param label The hash of the subnode label. - - (def 'get-record (node label) - (seq - (mstore node-bytes node) - (mstore label-bytes label) - (sha3 node-bytes 64))) - - ;; -------------------------------------------------------------------------- - ;; @notice Retrieves owner from node record. - ;; @param node Get owner of this node. - - (def 'get-owner (node) - (sload (+ node owner))) - - ;; -------------------------------------------------------------------------- - ;; @notice Stores new owner in node record. - ;; @param node Set owner of this node. - ;; @param new-owner New owner of this node. - - (def 'set-owner (node new-owner) - (sstore (+ node owner) new-owner)) - - ;; -------------------------------------------------------------------------- - ;; @notice Stores new subnode owner in node record. - ;; @param node Set owner of this node. - ;; @param label The hash of the label specifying the subnode. - ;; @param new-owner New owner of the subnode. - - (def 'set-subowner (node label new-owner) - (sstore (+ (get-record node label) owner) new-owner)) - - ;; -------------------------------------------------------------------------- - ;; @notice Retrieves resolver from node record. - ;; @param node Get resolver of this node. - - (def 'get-resolver (node) - (sload node)) - - ;; -------------------------------------------------------------------------- - ;; @notice Stores new resolver in node record. - ;; @param node Set resolver of this node. - ;; @param new-resolver New resolver for this node. - - (def 'set-resolver (node new-resolver) - (sstore node new-resolver)) - - ;; -------------------------------------------------------------------------- - ;; @notice Retrieves TTL From node record. - ;; @param node Get TTL of this node. - - (def 'get-ttl (node) - (sload (+ node ttl))) - - ;; -------------------------------------------------------------------------- - ;; @notice Stores new TTL in node record. - ;; @param node Set TTL of this node. - ;; @param new-resolver New TTL for this node. - - (def 'set-ttl (node new-ttl) - (sstore (+ node ttl) new-ttl)) - - ;; -------------------------------------------------------------------------- - ;; @notice Checks that the caller is the node owner. - ;; @param node Check owner of this node. - - (def 'only-node-owner (node) - (when (!= (caller) (get-owner node)) - (jump invalid-location))) - - ;; -------------------------------------------------------------------------- - ;; INIT - - ;; Set the owner of the root node (0x00) to the deploying account. - (set-owner 0x00 (caller)) - - ;; -------------------------------------------------------------------------- - ;; CODE - - (returnlll - (seq - - ;; ---------------------------------------------------------------------- - ;; @notice Returns the address of the resolver for the specified node. - ;; @dev Signature: resolver(bytes32) - ;; @param node Return this node's resolver. - ;; @return The associated resolver. - - (def 'node (calldataload 0x04)) - - (function get-node-resolver - (seq - - ;; Get the node's resolver and save it. - (mstore call-result (get-resolver node)) - - ;; Return result. - (return call-result 32))) - - ;; ---------------------------------------------------------------------- - ;; @notice Returns the address that owns the specified node. - ;; @dev Signature: owner(bytes32) - ;; @param node Return this node's owner. - ;; @return The associated address. - - (def 'node (calldataload 0x04)) - - (function get-node-owner - (seq - - ;; Get the node's owner and save it. - (mstore call-result (get-owner node)) - - ;; Return result. - (return call-result 32))) - - ;; ---------------------------------------------------------------------- - ;; @notice Returns the TTL of a node and any records associated with it. - ;; @dev Signature: ttl(bytes32) - ;; @param node Return this node's TTL. - ;; @return The node's TTL. - - (def 'node (calldataload 0x04)) - - (function get-node-ttl - (seq - - ;; Get the node's TTL and save it. - (mstore call-result (get-ttl node)) - - ;; Return result. - (return call-result 32))) - - ;; ---------------------------------------------------------------------- - ;; @notice Transfers ownership of a node to a new address. May only be - ;; called by the current owner of the node. - ;; @dev Signature: setOwner(bytes32,address) - ;; @param node The node to transfer ownership of. - ;; @param new-owner The address of the new owner. - - (def 'node (calldataload 0x04)) - (def 'new-owner (calldataload 0x24)) - - (function set-node-owner - (seq (only-node-owner node) - - ;; Transfer ownership by storing passed-in address. - (set-owner node new-owner) - - ;; Emit an event about the transfer. - ;; Transfer(bytes32 indexed node, address owner); - (mstore call-result new-owner) - (log2 call-result 32 - (sha3 0x00 (lit 0x00 "Transfer(bytes32,address)")) node) - - ;; Nothing to return. - (stop))) - - ;; ---------------------------------------------------------------------- - ;; @notice Transfers ownership of a subnode to a new address. May only be - ;; called by the owner of the parent node. - ;; @dev Signature: setSubnodeOwner(bytes32,bytes32,address) - ;; @param node The parent node. - ;; @param label The hash of the label specifying the subnode. - ;; @param new-owner The address of the new owner. - - (def 'node (calldataload 0x04)) - (def 'label (calldataload 0x24)) - (def 'new-owner (calldataload 0x44)) - - (function set-subnode-owner - (seq (only-node-owner node) - - ;; Transfer ownership by storing passed-in address. - (set-subowner node label new-owner) - - ;; Emit an event about the transfer. - ;; NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); - (mstore call-result new-owner) - (log3 call-result 32 - (sha3 0x00 (lit 0x00 "NewOwner(bytes32,bytes32,address)")) - node label) - - ;; Nothing to return. - (stop))) - - ;; ---------------------------------------------------------------------- - ;; @notice Sets the resolver address for the specified node. - ;; @dev Signature: setResolver(bytes32,address) - ;; @param node The node to update. - ;; @param new-resolver The address of the resolver. - - (def 'node (calldataload 0x04)) - (def 'new-resolver (calldataload 0x24)) - - (function set-node-resolver - (seq (only-node-owner node) - - ;; Transfer ownership by storing passed-in address. - (set-resolver node new-resolver) - - ;; Emit an event about the change of resolver. - ;; NewResolver(bytes32 indexed node, address resolver); - (mstore call-result new-resolver) - (log2 call-result 32 - (sha3 0x00 (lit 0x00 "NewResolver(bytes32,address)")) node) - - ;; Nothing to return. - (stop))) - - ;; ---------------------------------------------------------------------- - ;; @notice Sets the TTL for the specified node. - ;; @dev Signature: setTTL(bytes32,uint64) - ;; @param node The node to update. - ;; @param ttl The TTL in seconds. - - (def 'node (calldataload 0x04)) - (def 'new-ttl (calldataload 0x24)) - - (function set-node-ttl - (seq (only-node-owner node) - - ;; Set new TTL by storing passed-in time. - (set-ttl node new-ttl) - - ;; Emit an event about the change of TTL. - ;; NewTTL(bytes32 indexed node, uint64 ttl); - (mstore call-result new-ttl) - (log2 call-result 32 - (sha3 0x00 (lit 0x00 "NewTTL(bytes32,uint64)")) node) - - ;; Nothing to return. - (stop))) - - ;; ---------------------------------------------------------------------- - ;; @notice Fallback: No functions matched the function ID provided. - - (jump invalid-location))) - -) -)DELIMITER"; - -static unique_ptr s_compiledEns; - -class LLLENSTestFramework: public LLLExecutionFramework -{ -protected: - void deployEns() - { - if (!s_compiledEns) - { - vector errors; - s_compiledEns.reset(new bytes(compileLLL(ensCode, solidity::test::Options::get().evmVersion(), solidity::test::Options::get().optimize, &errors))); - BOOST_REQUIRE(errors.empty()); - } - sendMessage(*s_compiledEns, true); - BOOST_REQUIRE(m_transactionSuccessful); - BOOST_REQUIRE(!m_output.empty()); - } - -}; - -} - -// Test suite for the deployed ENS Registry implementation written in LLL -BOOST_FIXTURE_TEST_SUITE(LLLENS, LLLENSTestFramework) - -BOOST_AUTO_TEST_CASE(creation) -{ - deployEns(); - - // Root node 0x00 should initially be owned by the deploying account, account(0). - BOOST_CHECK(callContractFunction("owner(bytes32)", 0x00) == encodeArgs(ACCOUNT(0))); -} - -BOOST_AUTO_TEST_CASE(transfer_ownership) -{ - deployEns(); - - // Transfer ownership of root node from account(0) to account(1). - BOOST_REQUIRE(callContractFunction("setOwner(bytes32,address)", 0x00, ACCOUNT(1)) == encodeArgs()); - - // Check that an event was raised and contents are correct. - BOOST_REQUIRE(numLogs() == 1); - BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1))); - BOOST_REQUIRE(numLogTopics(0) == 2); - BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(bytes32,address)"))); - BOOST_CHECK(logTopic(0, 1) == u256(0x00)); - - // Verify that owner of 0x00 is now account(1). - BOOST_CHECK(callContractFunction("owner(bytes32)", 0x00) == encodeArgs(ACCOUNT(1))); -} - -BOOST_AUTO_TEST_CASE(transfer_ownership_fail) -{ - deployEns(); - - // Try to steal ownership of node 0x01 - BOOST_REQUIRE(callContractFunction("setOwner(bytes32,address)", 0x01, ACCOUNT(0)) == encodeArgs()); - - // Verify that owner of 0x01 remains the default zero address - BOOST_CHECK(callContractFunction("owner(bytes32)", 0x01) == encodeArgs(0)); -} - -BOOST_AUTO_TEST_CASE(set_resolver) -{ - deployEns(); - - // Set resolver of root node to account(1). - BOOST_REQUIRE(callContractFunction("setResolver(bytes32,address)", 0x00, ACCOUNT(1)) == encodeArgs()); - - // Check that an event was raised and contents are correct. - BOOST_REQUIRE(numLogs() == 1); - BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1))); - BOOST_REQUIRE(numLogTopics(0) == 2); - BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewResolver(bytes32,address)"))); - BOOST_CHECK(logTopic(0, 1) == u256(0x00)); - - // Verify that the resolver is changed to account(1). - BOOST_CHECK(callContractFunction("resolver(bytes32)", 0x00) == encodeArgs(ACCOUNT(1))); -} - -BOOST_AUTO_TEST_CASE(set_resolver_fail) -{ - deployEns(); - - // Try to set resolver of node 0x01, which is not owned by account(0). - BOOST_REQUIRE(callContractFunction("setResolver(bytes32,address)", 0x01, ACCOUNT(0)) == encodeArgs()); - - // Verify that the resolver of 0x01 remains default zero address. - BOOST_CHECK(callContractFunction("resolver(bytes32)", 0x01) == encodeArgs(0)); -} - -BOOST_AUTO_TEST_CASE(set_ttl) -{ - deployEns(); - - // Set ttl of root node to 3600. - BOOST_REQUIRE(callContractFunction("setTTL(bytes32,uint64)", 0x00, 3600) == encodeArgs()); - - // Check that an event was raised and contents are correct. - BOOST_REQUIRE(numLogs() == 1); - BOOST_CHECK(logData(0) == encodeArgs(3600)); - BOOST_REQUIRE(numLogTopics(0) == 2); - BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewTTL(bytes32,uint64)"))); - BOOST_CHECK(logTopic(0, 1) == u256(0x00)); - - // Verify that the TTL has been set. - BOOST_CHECK(callContractFunction("ttl(bytes32)", 0x00) == encodeArgs(3600)); -} - -BOOST_AUTO_TEST_CASE(set_ttl_fail) -{ - deployEns(); - - // Try to set TTL of node 0x01, which is not owned by account(0). - BOOST_REQUIRE(callContractFunction("setTTL(bytes32,uint64)", 0x01, 3600) == encodeArgs()); - - // Verify that the TTL of node 0x01 has not changed from the default. - BOOST_CHECK(callContractFunction("ttl(bytes32)", 0x01) == encodeArgs(0)); -} - -BOOST_AUTO_TEST_CASE(create_subnode) -{ - deployEns(); - - // Set ownership of "eth" sub-node to account(1) - BOOST_REQUIRE(callContractFunction("setSubnodeOwner(bytes32,bytes32,address)", 0x00, keccak256(string("eth")), ACCOUNT(1)) == encodeArgs()); - - // Check that an event was raised and contents are correct. - BOOST_REQUIRE(numLogs() == 1); - BOOST_CHECK(logData(0) == encodeArgs(ACCOUNT(1))); - BOOST_REQUIRE(numLogTopics(0) == 3); - BOOST_CHECK(logTopic(0, 0) == keccak256(string("NewOwner(bytes32,bytes32,address)"))); - BOOST_CHECK(logTopic(0, 1) == u256(0x00)); - BOOST_CHECK(logTopic(0, 2) == keccak256(string("eth"))); - - // Verify that the sub-node owner is now account(1). - u256 namehash = keccak256(h256(0x00).asBytes() + keccak256("eth").asBytes()); - BOOST_CHECK(callContractFunction("owner(bytes32)", namehash) == encodeArgs(ACCOUNT(1))); -} - -BOOST_AUTO_TEST_CASE(create_subnode_fail) -{ - deployEns(); - - // Send account(1) some ether for gas. - sendEther(account(1), 1000 * ether); - BOOST_REQUIRE(balanceAt(account(1)) >= 1000 * ether); - - // account(1) tries to set ownership of the "eth" sub-node. - m_sender = account(1); - BOOST_REQUIRE(callContractFunction("setSubnodeOwner(bytes32,bytes32,address)", 0x00, keccak256(string("eth")), ACCOUNT(1)) == encodeArgs()); - - // Verify that the sub-node owner remains at default zero address. - u256 namehash = keccak256(h256(0x00).asBytes() + keccak256("eth").asBytes()); - BOOST_CHECK(callContractFunction("owner(bytes32)", namehash) == encodeArgs(0)); -} - -BOOST_AUTO_TEST_CASE(fallback) -{ - deployEns(); - - // Call fallback - should just abort via jump to invalid location. - BOOST_CHECK(callFallback() == encodeArgs()); -} - -BOOST_AUTO_TEST_SUITE_END() - -} // end namespaces diff --git a/test/liblll/LLL_ERC20.cpp b/test/liblll/LLL_ERC20.cpp deleted file mode 100644 index 4047ede8a..000000000 --- a/test/liblll/LLL_ERC20.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @author Ben Edgington - * @date 2017 - * Tests for an ERC20 token implementation written in LLL - */ - -#include -#include -#include -#include - -#define TOKENSUPPLY 100000 -#define TOKENDECIMALS 2 -#define TOKENSYMBOL "BEN" -#define TOKENNAME "Ben Token" -#define ACCOUNT(n) h256(account(n), h256::AlignRight) -#define SUCCESS encodeArgs(1) - -using namespace std; -using namespace solidity::lll; -using namespace solidity::util; -using namespace solidity::test; - -namespace solidity::lll::test -{ - -namespace -{ - -static char const* erc20Code = R"DELIMITER( -(seq - - ;; -------------------------------------------------------------------------- - ;; CONSTANTS - - ;; Token parameters. - ;; 0x40 is a "magic number" - the text of the string is placed here - ;; when returning the string to the caller. See return-string below. - (def 'token-name-string (lit 0x40 "Ben Token")) - (def 'token-symbol-string (lit 0x40 "BEN")) - (def 'token-decimals 2) - (def 'token-supply 100000) ; 1000.00 total tokens - - ;; Booleans - (def 'false 0) - (def 'true 1) - - ;; Memory layout. - (def 'mem-ret 0x00) ; Fixed due to compiler macro for return. - (def 'mem-func 0x00) ; No conflict with mem-ret, so re-use. - (def 'mem-keccak 0x00) ; No conflict with mem-func or mem-ret, so re-use. - (def 'scratch0 0x20) - (def 'scratch1 0x40) - - ;; Precomputed function IDs. - (def 'get-name 0x06fdde03) ; name() - (def 'get-symbol 0x95d89b41) ; symbol() - (def 'get-decimals 0x313ce567) ; decimals() - (def 'get-total-supply 0x18160ddd) ; totalSupply() - (def 'get-balance-of 0x70a08231) ; balanceOf(address) - (def 'transfer 0xa9059cbb) ; transfer(address,uint256) - (def 'transfer-from 0x23b872dd) ; transferFrom(address,address,uint256) - (def 'approve 0x095ea7b3) ; approve(address,uint256) - (def 'get-allowance 0xdd62ed3e) ; allowance(address,address) - - ;; Event IDs - (def 'transfer-event-id ; Transfer(address,address,uint256) - 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef) - - (def 'approval-event-id ; Approval(address,address,uint256) - 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925) - - ;; -------------------------------------------------------------------------- - ;; UTILITIES - - ;; -------------------------------------------------------------------------- - ;; The following define the key data-structures: - ;; - balance(addr) => value - ;; - allowance(addr,addr) => value - - ;; Balances are stored at s[owner_addr]. - (def 'balance (address) address) - - ;; Allowances are stored at s[owner_addr + keccak256(spender_addr)] - ;; We use a crypto function here to avoid any situation where - ;; approve(me, spender) can be abused to do approve(target, me). - (def 'allowance (owner spender) - (seq - (mstore mem-keccak spender) - (keccak256 mem-keccak 0x20))) - - ;; -------------------------------------------------------------------------- - ;; For convenience we have macros to refer to function arguments - - (def 'arg1 (calldataload 0x04)) - (def 'arg2 (calldataload 0x24)) - (def 'arg3 (calldataload 0x44)) - - ;; -------------------------------------------------------------------------- - ;; Revert is a soft return that does not consume the remaining gas. - ;; We use it when rejecting invalid user input. - ;; - ;; Note: The REVERT opcode will be implemented in Metropolis (EIP 140). - ;; Meanwhile it just causes an invalid instruction exception (similar - ;; to a "throw" in Solidity). When fully implemented, Revert could be - ;; use to return error codes, or even messages. - - (def 'revert () (revert 0 0)) - - ;; -------------------------------------------------------------------------- - ;; Macro for returning string names. - ;; Compliant with the ABI format for strings. - - (def 'return-string (string-literal) - (seq - (mstore 0x00 0x20) ; Points to our string's memory location - (mstore 0x20 string-literal) ; Length. String itself is copied to 0x40. - (return 0x00 (& (+ (mload 0x20) 0x5f) (~ 0x1f))))) - ; Round return up to 32 byte boundary - - ;; -------------------------------------------------------------------------- - ;; Convenience macro for raising Events - - (def 'event3 (id addr1 addr2 value) - (seq - (mstore scratch0 value) - (log3 scratch0 0x20 id addr1 addr2))) - - ;; -------------------------------------------------------------------------- - ;; Determines whether the stored function ID matches a known - ;; function hash and executes if so. - ;; @param function-hash The four-byte hash of a known function signature. - ;; @param code-body The code to run in the case of a match. - - (def 'function (function-hash code-body) - (when (= (mload mem-func) function-hash) - code-body)) - - ;; -------------------------------------------------------------------------- - ;; Gets the function ID and stores it in memory for reference. - ;; The function ID is in the leftmost four bytes of the call data. - - (def 'uses-functions - (mstore - mem-func - (shr (calldataload 0x00) 224))) - - ;; -------------------------------------------------------------------------- - ;; GUARDS - - ;; -------------------------------------------------------------------------- - ;; Checks that ensure that each function is called with the right - ;; number of arguments. For one thing this addresses the "ERC20 - ;; short address attack". For another, it stops me making - ;; mistakes while testing. We use these only on the non-constant functions. - - (def 'has-one-arg (unless (= 0x24 (calldatasize)) (revert))) - (def 'has-two-args (unless (= 0x44 (calldatasize)) (revert))) - (def 'has-three-args (unless (= 0x64 (calldatasize)) (revert))) - - ;; -------------------------------------------------------------------------- - ;; Check that addresses have only 160 bits and revert if not. - ;; We use these input type-checks on the non-constant functions. - - (def 'is-address (addr) - (when - (shr addr 160) - (revert))) - - ;; -------------------------------------------------------------------------- - ;; Check that transfer values are smaller than total supply and - ;; revert if not. This should effectively exclude negative values. - - (def 'is-value (value) - (when (> value token-supply) (revert))) - - ;; -------------------------------------------------------------------------- - ;; Will revert if sent any Ether. We use the macro immediately so as - ;; to abort if sent any Ether during contract deployment. - - (def 'not-payable - (when (callvalue) (revert))) - - not-payable - - ;; -------------------------------------------------------------------------- - ;; INITIALISATION - ;; - ;; Assign all tokens initially to the owner of the contract. - - (sstore (balance (caller)) token-supply) - - ;; -------------------------------------------------------------------------- - ;; CONTRACT CODE - - (returnlll - (seq not-payable uses-functions - - ;; ---------------------------------------------------------------------- - ;; Getter for the name of the token. - ;; @abi name() constant returns (string) - ;; @return The token name as a string. - - (function get-name - (return-string token-name-string)) - - ;; ---------------------------------------------------------------------- - ;; Getter for the symbol of the token. - ;; @abi symbol() constant returns (string) - ;; @return The token symbol as a string. - - (function get-symbol - (return-string token-symbol-string)) - - ;; ---------------------------------------------------------------------- - ;; Getter for the number of decimals assigned to the token. - ;; @abi decimals() constant returns (uint256) - ;; @return The token decimals. - - (function get-decimals - (return token-decimals)) - - ;; ---------------------------------------------------------------------- - ;; Getter for the total token supply. - ;; @abi totalSupply() constant returns (uint256) - ;; @return The token supply. - - (function get-total-supply - (return token-supply)) - - ;; ---------------------------------------------------------------------- - ;; Returns the account balance of another account. - ;; @abi balanceOf(address) constant returns (uint256) - ;; @param owner The address of the account's owner. - ;; @return The account balance. - - (function get-balance-of - (seq - - (def 'owner arg1) - - (return (sload (balance owner))))) - - ;; ---------------------------------------------------------------------- - ;; Transfers _value amount of tokens to address _to. The command - ;; should throw if the _from account balance has not enough - ;; tokens to spend. - ;; @abi transfer(address, uint256) returns (bool) - ;; @param to The account to receive the tokens. - ;; @param value The quantity of tokens to transfer. - ;; @return Success (true). Other outcomes result in a Revert. - - (function transfer - (seq has-two-args (is-address arg1) (is-value arg2) - - (def 'to arg1) - (def 'value arg2) - - (when value ; value == 0 is a no-op - (seq - - ;; The caller's balance. Save in memory for efficiency. - (mstore scratch0 (sload (balance (caller)))) - - ;; Revert if the caller's balance is not sufficient. - (when (> value (mload scratch0)) - (revert)) - - ;; Make the transfer - ;; It would be good to check invariants (sum of balances). - (sstore (balance (caller)) (- (mload scratch0) value)) - (sstore (balance to) (+ (sload (balance to)) value)) - - ;; Event - Transfer(address,address,uint256) - (event3 transfer-event-id (caller) to value))) - - (return true))) - - ;; ---------------------------------------------------------------------- - ;; Send _value amount of tokens from address _from to address _to - ;; @abi transferFrom(address,address,uint256) returns (bool) - ;; @param from The account to send the tokens from. - ;; @param to The account to receive the tokens. - ;; @param value The quantity of tokens to transfer. - ;; @return Success (true). Other outcomes result in a Revert. - - (function transfer-from - (seq has-three-args (is-address arg1) (is-address arg2) (is-value arg3) - - (def 'from arg1) - (def 'to arg2) - (def 'value arg3) - - (when value ; value == 0 is a no-op - - (seq - - ;; Save data to memory for efficiency. - (mstore scratch0 (sload (balance from))) - (mstore scratch1 (sload (allowance from (caller)))) - - ;; Revert if not enough funds, or not enough approved. - (when - (|| - (> value (mload scratch0)) - (> value (mload scratch1))) - (revert)) - - ;; Make the transfer and update allowance. - (sstore (balance from) (- (mload scratch0) value)) - (sstore (balance to) (+ (sload (balance to)) value)) - (sstore (allowance from (caller)) (- (mload scratch1) value)) - - ;; Event - Transfer(address,address,uint256) - (event3 transfer-event-id from to value))) - - (return true))) - - ;; ---------------------------------------------------------------------- - ;; Allows _spender to withdraw from your account multiple times, - ;; up to the _value amount. If this function is called again it - ;; overwrites the current allowance with _value. - ;; @abi approve(address,uint256) returns (bool) - ;; @param spender The withdrawing account having its limit set. - ;; @param value The maximum allowed amount. - ;; @return Success (true). Other outcomes result in a Revert. - - (function approve - (seq has-two-args (is-address arg1) (is-value arg2) - - (def 'spender arg1) - (def 'value arg2) - - ;; Force users set the allowance to 0 before setting it to - ;; another value for the same spender. Prevents this attack: - ;; https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM - (when - (&& value (sload (allowance (caller) spender))) - (revert)) - - (sstore (allowance (caller) spender) value) - - ;; Event - Approval(address,address,uint256) - (event3 approval-event-id (caller) spender value) - - (return true))) - - ;; ---------------------------------------------------------------------- - ;; Returns the amount which _spender is still allowed to withdraw - ;; from _owner. - ;; @abi allowance(address,address) constant returns (uint256) - ;; @param owner The owning account. - ;; @param spender The withdrawing account. - ;; @return The allowed amount remaining. - - (function get-allowance - (seq - - (def 'owner arg1) - (def 'spender arg2) - - (return (sload (allowance owner spender))))) - - ;; ---------------------------------------------------------------------- - ;; Fallback: No functions matched the function ID provided. - - (revert))) - ) -)DELIMITER"; - -static unique_ptr s_compiledErc20; - -class LLLERC20TestFramework: public LLLExecutionFramework -{ -protected: - void deployErc20() - { - if (!s_compiledErc20) - { - vector errors; - s_compiledErc20.reset(new bytes(compileLLL(erc20Code, solidity::test::Options::get().evmVersion(), solidity::test::Options::get().optimize, &errors))); - BOOST_REQUIRE(errors.empty()); - } - sendMessage(*s_compiledErc20, true); - BOOST_REQUIRE(m_transactionSuccessful); - BOOST_REQUIRE(!m_output.empty()); - } - -}; - -} - -// Test suite for an ERC20 contract written in LLL. -BOOST_FIXTURE_TEST_SUITE(LLLERC20, LLLERC20TestFramework) - -BOOST_AUTO_TEST_CASE(creation) -{ - deployErc20(); - - // All tokens are initially assigned to the contract creator. - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY)); -} - -BOOST_AUTO_TEST_CASE(constants) -{ - deployErc20(); - - BOOST_CHECK(callContractFunction("totalSupply()") == encodeArgs(TOKENSUPPLY)); - BOOST_CHECK(callContractFunction("decimals()") == encodeArgs(TOKENDECIMALS)); - BOOST_CHECK(callContractFunction("symbol()") == encodeDyn(string(TOKENSYMBOL))); - BOOST_CHECK(callContractFunction("name()") == encodeDyn(string(TOKENNAME))); -} - -BOOST_AUTO_TEST_CASE(send_value) -{ - deployErc20(); - - // Send value to the contract. Should always fail. - m_sender = account(0); - auto contractBalance = balanceAt(m_contractAddress); - - // Fallback: check value is not transferred. - BOOST_CHECK(callFallbackWithValue(42) != SUCCESS); - BOOST_CHECK(balanceAt(m_contractAddress) == contractBalance); - - // Transfer: check nothing happened. - BOOST_CHECK(callContractFunctionWithValue("transfer(address,uint256)", ACCOUNT(1), 100, 42) != SUCCESS); - BOOST_CHECK(balanceAt(m_contractAddress) == contractBalance); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(1)) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY)); -} - -BOOST_AUTO_TEST_CASE(transfer) -{ - deployErc20(); - - // Transfer 100 tokens from account(0) to account(1). - int transfer = 100; - m_sender = account(0); - BOOST_CHECK(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) == SUCCESS); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY - transfer)); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(1)) == encodeArgs(transfer)); -} - -BOOST_AUTO_TEST_CASE(transfer_from) -{ - deployErc20(); - - // Approve account(1) to transfer up to 1000 tokens from account(0). - int allow = 1000; - m_sender = account(0); - BOOST_REQUIRE(callContractFunction("approve(address,uint256)", ACCOUNT(1), u256(allow)) == SUCCESS); - BOOST_REQUIRE(callContractFunction("allowance(address,address)", ACCOUNT(0), ACCOUNT(1)) == encodeArgs(allow)); - - // Send account(1) some ether for gas. - sendEther(account(1), 1000 * ether); - BOOST_REQUIRE(balanceAt(account(1)) >= 1000 * ether); - - // Transfer 300 tokens from account(0) to account(2); check that the allowance decreases. - int transfer = 300; - m_sender = account(1); - BOOST_REQUIRE(callContractFunction("transferFrom(address,address,uint256)", ACCOUNT(0), ACCOUNT(2), u256(transfer)) == SUCCESS); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(2)) == encodeArgs(transfer)); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY - transfer)); - BOOST_CHECK(callContractFunction("allowance(address,address)", ACCOUNT(0), ACCOUNT(1)) == encodeArgs(allow - transfer)); -} - -BOOST_AUTO_TEST_CASE(transfer_event) -{ - deployErc20(); - - // Transfer 1000 tokens from account(0) to account(1). - int transfer = 1000; - m_sender = account(0); - BOOST_REQUIRE(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) == SUCCESS); - - // Check that a Transfer event was recorded and contents are correct. - BOOST_REQUIRE(numLogs() == 1); - BOOST_CHECK(logData(0) == encodeArgs(transfer)); - BOOST_REQUIRE(numLogTopics(0) == 3); - BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(address,address,uint256)"))); - BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0)); - BOOST_CHECK(logTopic(0, 2) == ACCOUNT(1)); -} - -BOOST_AUTO_TEST_CASE(transfer_zero_no_event) -{ - deployErc20(); - - // Transfer 0 tokens from account(0) to account(1). This is a no-op. - int transfer = 0; - m_sender = account(0); - BOOST_REQUIRE(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) == SUCCESS); - - // Check that no Event was recorded. - BOOST_CHECK(numLogs() == 0); - - // Check that balances have not changed. - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY - transfer)); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(1)) == encodeArgs(transfer)); -} - -BOOST_AUTO_TEST_CASE(approval_and_transfer_events) -{ - deployErc20(); - - // Approve account(1) to transfer up to 10000 tokens from account(0). - int allow = 10000; - m_sender = account(0); - BOOST_REQUIRE(callContractFunction("approve(address,uint256)", ACCOUNT(1), u256(allow)) == SUCCESS); - - // Check that an Approval event was recorded and contents are correct. - BOOST_REQUIRE(numLogs() == 1); - BOOST_CHECK(logData(0) == encodeArgs(allow)); - BOOST_REQUIRE(numLogTopics(0) == 3); - BOOST_CHECK(logTopic(0, 0) == keccak256(string("Approval(address,address,uint256)"))); - BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0)); - BOOST_CHECK(logTopic(0, 2) == ACCOUNT(1)); - - // Send account(1) some ether for gas. - sendEther(account(1), 1000 * ether); - BOOST_REQUIRE(balanceAt(account(1)) >= 1000 * ether); - - // Transfer 3000 tokens from account(0) to account(2); check that the allowance decreases. - int transfer = 3000; - m_sender = account(1); - BOOST_REQUIRE(callContractFunction("transferFrom(address,address,uint256)", ACCOUNT(0), ACCOUNT(2), u256(transfer)) == SUCCESS); - - // Check that a Transfer event was recorded and contents are correct. - BOOST_REQUIRE(numLogs() == 1); - BOOST_CHECK(logData(0) == encodeArgs(transfer)); - BOOST_REQUIRE(numLogTopics(0) == 3); - BOOST_CHECK(logTopic(0, 0) == keccak256(string("Transfer(address,address,uint256)"))); - BOOST_CHECK(logTopic(0, 1) == ACCOUNT(0)); - BOOST_CHECK(logTopic(0, 2) == ACCOUNT(2)); -} - -BOOST_AUTO_TEST_CASE(invalid_transfer_1) -{ - deployErc20(); - - // Transfer more than the total supply; ensure nothing changes. - int transfer = TOKENSUPPLY + 1; - m_sender = account(0); - BOOST_CHECK(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) != SUCCESS); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY)); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(1)) == encodeArgs(0)); -} - -BOOST_AUTO_TEST_CASE(invalid_transfer_2) -{ - deployErc20(); - - // Separate transfers that together exceed initial balance. - int transfer = 1 + TOKENSUPPLY / 2; - m_sender = account(0); - - // First transfer should succeed. - BOOST_REQUIRE(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) == SUCCESS); - BOOST_REQUIRE(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY - transfer)); - BOOST_REQUIRE(callContractFunction("balanceOf(address)", ACCOUNT(1)) == encodeArgs(transfer)); - - // Second transfer should fail. - BOOST_CHECK(callContractFunction("transfer(address,uint256)", ACCOUNT(1), u256(transfer)) != SUCCESS); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY - transfer)); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(1)) == encodeArgs(transfer)); -} - -BOOST_AUTO_TEST_CASE(invalid_transfer_from) -{ - deployErc20(); - - // TransferFrom without approval. - int transfer = 300; - - // Send account(1) some ether for gas. - m_sender = account(0); - sendEther(account(1), 1000 * ether); - BOOST_REQUIRE(balanceAt(account(1)) >= 1000 * ether); - - // Try the transfer; ensure nothing changes. - m_sender = account(1); - BOOST_CHECK(callContractFunction("transferFrom(address,address,uint256)", ACCOUNT(0), ACCOUNT(2), u256(transfer)) != SUCCESS); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(2)) == encodeArgs(0)); - BOOST_CHECK(callContractFunction("balanceOf(address)", ACCOUNT(0)) == encodeArgs(TOKENSUPPLY)); - BOOST_CHECK(callContractFunction("allowance(address,address)", ACCOUNT(0), ACCOUNT(1)) == encodeArgs(0)); -} - -BOOST_AUTO_TEST_CASE(invalid_reapprove) -{ - deployErc20(); - - m_sender = account(0); - - // Approve account(1) to transfer up to 1000 tokens from account(0). - int allow1 = 1000; - BOOST_REQUIRE(callContractFunction("approve(address,uint256)", ACCOUNT(1), u256(allow1)) == SUCCESS); - BOOST_REQUIRE(callContractFunction("allowance(address,address)", ACCOUNT(0), ACCOUNT(1)) == encodeArgs(allow1)); - - // Now approve account(1) to transfer up to 500 tokens from account(0). - // Should fail (we need to reset allowance to 0 first). - int allow2 = 500; - BOOST_CHECK(callContractFunction("approve(address,uint256)", ACCOUNT(1), u256(allow2)) != SUCCESS); - BOOST_CHECK(callContractFunction("allowance(address,address)", ACCOUNT(0), ACCOUNT(1)) == encodeArgs(allow1)); -} - -BOOST_AUTO_TEST_CASE(bad_data) -{ - deployErc20(); - - m_sender = account(0); - - // Correct data: transfer(address _to, 1). - sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a123456789a") + encodeArgs(1), false, 0); - BOOST_CHECK(m_transactionSuccessful); - BOOST_CHECK(m_output == SUCCESS); - - // Too little data (address is truncated by one byte). - sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a12345678") + encodeArgs(1), false, 0); - BOOST_CHECK(!m_transactionSuccessful); - BOOST_CHECK(m_output != SUCCESS); - - // Too much data (address is extended with a zero byte). - sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000000123456789a123456789a123456789a123456789a00") + encodeArgs(1), false, 0); - BOOST_CHECK(!m_transactionSuccessful); - BOOST_CHECK(m_output != SUCCESS); - - // Invalid address (a bit above the 160th is set). - sendMessage((bytes)fromHex("a9059cbb") + (bytes)fromHex("000000000000000000000100123456789a123456789a123456789a123456789a") + encodeArgs(1), false, 0); - BOOST_CHECK(!m_transactionSuccessful); - BOOST_CHECK(m_output != SUCCESS); -} - -BOOST_AUTO_TEST_SUITE_END() - -} // end namespaces diff --git a/test/liblll/Parser.cpp b/test/liblll/Parser.cpp deleted file mode 100644 index bfee38171..000000000 --- a/test/liblll/Parser.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @author Alex Beregszaszi - * @date 2016 - * Unit tests for the LLL parser. - */ - -#include -#include -#include -#include - -using namespace std; - -namespace solidity::lll::test -{ - -namespace -{ - -bool successParse(std::string const& _source) -{ - std::string ret = lll::parseLLL(_source); - return ret.size() != 0; -} - -std::string parse(std::string const& _source) -{ - return lll::parseLLL(_source); -} - -} - -BOOST_AUTO_TEST_SUITE(LLLParser) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - char const* text = "1"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(string) -{ - char const* text = "\"string\""; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"("string")"); -} - -BOOST_AUTO_TEST_CASE(symbol) -{ - char const* text = "symbol"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"(symbol)"); - - BOOST_CHECK(successParse("'symbol")); - BOOST_CHECK_EQUAL(parse(text), R"(symbol)"); -} - -BOOST_AUTO_TEST_CASE(decimals) -{ - char const* text = "1234"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"(1234)"); -} - -BOOST_AUTO_TEST_CASE(hexadecimals) -{ - char const* text = "0x1234"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"(4660)"); - - BOOST_CHECK(!successParse("0x")); -} - -BOOST_AUTO_TEST_CASE(sequence) -{ - char const* text = "{ 1234 }"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"({ 1234 })"); -} - -BOOST_AUTO_TEST_CASE(empty_sequence) -{ - char const* text = "{}"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"({ })"); -} - -BOOST_AUTO_TEST_CASE(mload) -{ - char const* text = "@0"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"(@ 0)"); - - BOOST_CHECK(successParse("@0x0")); - BOOST_CHECK(successParse("@symbol")); - BOOST_CHECK(!successParse("@")); -} - -BOOST_AUTO_TEST_CASE(sload) -{ - char const* text = "@@0"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"(@@ 0)"); - - BOOST_CHECK(successParse("@@0x0")); - BOOST_CHECK(successParse("@@symbol")); - BOOST_CHECK(!successParse("@@")); -} - -BOOST_AUTO_TEST_CASE(mstore) -{ - char const* text = "[0]:0"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"([ 0 ] 0)"); - - BOOST_CHECK(successParse("[0] 0")); - BOOST_CHECK(successParse("[0x0]:0x0")); - BOOST_CHECK(successParse("[symbol]:symbol")); - BOOST_CHECK(!successParse("[]")); - BOOST_CHECK(!successParse("[0]")); -} - -BOOST_AUTO_TEST_CASE(sstore) -{ - char const* text = "[[0]]:0"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"([[ 0 ]] 0)"); - - BOOST_CHECK(successParse("[[0]] 0")); - BOOST_CHECK(successParse("[[0x0]]:0x0")); - BOOST_CHECK(successParse("[[symbol]]:symbol")); - BOOST_CHECK(!successParse("[[]]")); - BOOST_CHECK(!successParse("[[0x0]]")); -} - -BOOST_AUTO_TEST_CASE(calldataload) -{ - char const* text = "$0"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"($ 0)"); - - BOOST_CHECK(successParse("$0x0")); - BOOST_CHECK(successParse("$symbol")); - BOOST_CHECK(!successParse("$")); -} - -BOOST_AUTO_TEST_CASE(list) -{ - char const* text = "( 1234 )"; - BOOST_CHECK(successParse(text)); - BOOST_CHECK_EQUAL(parse(text), R"(( 1234 ))"); - - BOOST_CHECK(successParse("( 1234 5467 )")); - BOOST_CHECK(successParse("()")); -} - -BOOST_AUTO_TEST_CASE(macro_with_zero_args) -{ - char const* text = "(def 'zeroargs () (asm INVALID))"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_SUITE_END() - -} // end namespaces From 8d7fd90593bf99519f9a0b7b23867a90b1146577 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 10 Dec 2019 23:51:19 +0000 Subject: [PATCH 2/6] Remove LLL from docs --- docs/index.rst | 1 - docs/lll.rst | 21 --------------------- 2 files changed, 22 deletions(-) delete mode 100644 docs/lll.rst diff --git a/docs/index.rst b/docs/index.rst index 199243018..6610b5217 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -104,4 +104,3 @@ Contents common-patterns.rst bugs.rst contributing.rst - lll.rst diff --git a/docs/lll.rst b/docs/lll.rst deleted file mode 100644 index 16be829e6..000000000 --- a/docs/lll.rst +++ /dev/null @@ -1,21 +0,0 @@ -### -LLL -### - -.. _lll: - -LLL is a low-level language for the EVM with an s-expressions syntax. - -The Solidity repository contains an LLL compiler, which shares the assembler subsystem with Solidity. -However, apart from maintaining that it still compiles, no other improvements are made to it. - -It is not built unless specifically requested: - -.. code-block:: bash - - $ cmake -DLLL=ON .. - $ cmake --build . - -.. warning:: - - The LLL codebase is deprecated and will be removed from the Solidity repository in the future. From 09a909905717b96b9b520c169f004b852b2c5aa0 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 13 Jan 2020 15:42:42 +0000 Subject: [PATCH 3/6] Mention in changelog --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 116e6f7a3..abc62fc80 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: + * LLL: The LLL compiler has been removed. * General: Raise warning if runtime bytecode exceeds 24576 bytes (a limit introduced in Spurious Dragon). * General: Support compiling starting from an imported AST. Among others, this can be used for mutation testing. * Yul Optimizer: Apply penalty when trying to rematerialize into loops. From f35e2bde31015f19113239384907942ecb911819 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 13 Jan 2020 15:46:52 +0000 Subject: [PATCH 4/6] Remove LLL from Circleci --- .circleci/config.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c2e64a764..868b292b2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -295,7 +295,6 @@ jobs: environment: CC: clang CXX: clang++ - CMAKE_OPTIONS: -DLLL=ON steps: - checkout - run: *run_build @@ -305,8 +304,6 @@ jobs: b_ubu: &build_ubuntu1904 docker: - image: ethereum/solidity-buildpack-deps:ubuntu1904-<< pipeline.parameters.docker-image-rev >> - environment: - CMAKE_OPTIONS: -DLLL=ON steps: - checkout - run: *run_build @@ -317,13 +314,12 @@ jobs: <<: *build_ubuntu1904 environment: FORCE_RELEASE: ON - CMAKE_OPTIONS: -DLLL=ON b_ubu18: &build_ubuntu1804 docker: - image: ethereum/solidity-buildpack-deps:ubuntu1804-<< pipeline.parameters.docker-image-rev >> environment: - CMAKE_OPTIONS: -DCMAKE_CXX_FLAGS=-O2 -DLLL=ON + CMAKE_OPTIONS: -DCMAKE_CXX_FLAGS=-O2 CMAKE_BUILD_TYPE: RelWithDebugInfo steps: - checkout @@ -368,7 +364,7 @@ jobs: <<: *build_ubuntu1904 environment: CMAKE_BUILD_TYPE: Debug - CMAKE_OPTIONS: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/cxx20.cmake -DUSE_CVC4=OFF -DLLL=ON + CMAKE_OPTIONS: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/cxx20.cmake -DUSE_CVC4=OFF steps: - checkout - run: *run_build @@ -408,7 +404,6 @@ jobs: - image: archlinux/base environment: TERM: xterm - CMAKE_OPTIONS: -DLLL=ON steps: - run: name: Install build dependencies @@ -425,7 +420,6 @@ jobs: environment: TERM: xterm CMAKE_BUILD_TYPE: Debug - CMAKE_OPTIONS: -DLLL=ON steps: - checkout - restore_cache: From 106ac296b90fc9b0f694a6131bb1d1cea5ecac46 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Jan 2020 12:27:07 +0000 Subject: [PATCH 5/6] Remove LLL from release scripts --- scripts/release.sh | 1 - scripts/release_ppa.sh | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/release.sh b/scripts/release.sh index ebc7759f5..a2f2fa875 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -39,7 +39,6 @@ mkdir -p $ZIP_TEMP_DIR # Copy all the solidity executables into a temporary directory prior to ZIP creation -cp $REPO_ROOT/build/lllc/lllc $ZIP_TEMP_DIR cp $REPO_ROOT/build/solc/solc $ZIP_TEMP_DIR # For macOS, we run a fix-up script which alters all of the symbolic links within diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 90ef3c943..5b5ca728f 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -156,7 +156,6 @@ Package: solc Architecture: any-i386 any-amd64 Multi-Arch: same Depends: \${shlibs:Depends}, \${misc:Depends} -Replaces: lllc (<< 1:0.3.6) Conflicts: libethereum (<= 1.2.9) Description: Solidity compiler. The commandline interface to the Solidity smart contract compiler. @@ -194,7 +193,7 @@ override_dh_shlibdeps: dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info override_dh_auto_configure: - dh_auto_configure -- -DINSTALL_LLLC=Off -DTESTS=OFF ${CMAKE_OPTIONS} + dh_auto_configure -- -DTESTS=OFF ${CMAKE_OPTIONS} EOF cat < debian/copyright Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ From 9c19b93c3735c45ef995a96f0a7bdd022cc36282 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Jan 2020 12:55:30 +0000 Subject: [PATCH 6/6] Remove LLL specific features from libevmasm --- libevmasm/Assembly.cpp | 49 +----------------------------------- libevmasm/Assembly.h | 13 ---------- test/libevmasm/Assembler.cpp | 9 ++----- 3 files changed, 3 insertions(+), 68 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index ad4263869..adc7f5b14 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -38,48 +38,6 @@ using namespace solidity::evmasm; using namespace solidity::langutil; using namespace solidity::util; -void Assembly::append(Assembly const& _a) -{ - auto newDeposit = m_deposit + _a.deposit(); - for (AssemblyItem i: _a.m_items) - { - switch (i.type()) - { - case Tag: - case PushTag: - i.setData(i.data() + m_usedTags); - break; - case PushSub: - case PushSubSize: - i.setData(i.data() + m_subs.size()); - break; - default: - break; - } - append(i); - } - m_deposit = newDeposit; - m_usedTags += _a.m_usedTags; - // This does not transfer the names of named tags on purpose. The tags themselves are - // transferred, but their names are only available inside the assembly. - for (auto const& i: _a.m_data) - m_data.insert(i); - for (auto const& i: _a.m_strings) - m_strings.insert(i); - m_subs += _a.m_subs; - for (auto const& lib: _a.m_libraries) - m_libraries.insert(lib); -} - -void Assembly::append(Assembly const& _a, int _deposit) -{ - assertThrow(_deposit <= _a.m_deposit, InvalidDeposit, ""); - - append(_a); - while (_deposit++ < _a.m_deposit) - append(Instruction::POP); -} - AssemblyItem const& Assembly::append(AssemblyItem const& _i) { assertThrow(m_deposit >= 0, AssemblyException, "Stack underflow."); @@ -88,12 +46,7 @@ AssemblyItem const& Assembly::append(AssemblyItem const& _i) if (m_items.back().location().isEmpty() && !m_currentSourceLocation.isEmpty()) m_items.back().setLocation(m_currentSourceLocation); m_items.back().m_modifierDepth = m_currentModifierDepth; - return back(); -} - -void Assembly::injectStart(AssemblyItem const& _i) -{ - m_items.insert(m_items.begin(), _i); + return m_items.back(); } unsigned Assembly::bytesRequired(unsigned subTagSize) const diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 9e146be01..e859951bd 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -56,7 +56,6 @@ public: AssemblyItem newPushLibraryAddress(std::string const& _identifier); AssemblyItem const& append(AssemblyItem const& _i); - AssemblyItem const& append(std::string const& _data) { return append(newPushString(_data)); } AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); } template Assembly& operator<<(T const& _d) { append(_d); return *this; } @@ -137,18 +136,6 @@ public: StringMap const& _sourceCodes = StringMap() ) const; -public: - // These features are only used by LLL - AssemblyItem newPushString(std::string const& _data) { util::h256 h(util::keccak256(_data)); m_strings[h] = _data; return AssemblyItem(PushString, h); } - - void append(Assembly const& _a); - void append(Assembly const& _a, int _deposit); - - void injectStart(AssemblyItem const& _i); - - AssemblyItem const& back() const { return m_items.back(); } - std::string backString() const { return m_items.size() && m_items.back().type() == PushString ? m_strings.at((util::h256)m_items.back().data()) : std::string(); } - protected: /// Does the same operations as @a optimise, but should only be applied to a sub and /// returns the replaced tags. Also takes an argument containing the tags of this assembly diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index f03c9fbb9..31b30dd45 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -74,8 +74,6 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) _assembly.appendLibraryAddress("someLibrary"); // PushTag + Operation _assembly.appendJump(tag); - // PushString - _assembly.append("Unused feature for pushing string"); // PushData _assembly.append(bytes{0x1, 0x2, 0x3, 0x4}); // PushSubSize @@ -93,9 +91,8 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) BOOST_CHECK_EQUAL( _assembly.assemble().toHex(), - "5b6001600220606773__$bf005014d9d0f534b8fcb268bd84c491a2$__" - "6000567f556e75736564206665617475726520666f722070757368696e" - "6720737472696e605f6001605e73000000000000000000000000000000000000000000fe" + "5b6001600220604673__$bf005014d9d0f534b8fcb268bd84c491a2$__" + "600056603e6001603d73000000000000000000000000000000000000000000fe" "fe010203044266eeaa" ); BOOST_CHECK_EQUAL( @@ -106,7 +103,6 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) " bytecodeSize\n" " linkerSymbol(\"bf005014d9d0f534b8fcb268bd84c491a2380f4acd260d1ccfe9cd8201f7e994\")\n" " jump(tag_1)\n" - " data_027497964124140851e8a9992ba16b5c1aaf9730b78d6036c8d65e3bb5ea4c8f\n" " data_a6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b\n" " dataSize(sub_0)\n" " dataOffset(sub_0)\n" @@ -133,7 +129,6 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) "{\"begin\":1,\"end\":3,\"name\":\"PUSHLIB\",\"value\":\"someLibrary\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH [tag]\",\"value\":\"1\"}," "{\"begin\":1,\"end\":3,\"name\":\"JUMP\"}," - "{\"begin\":1,\"end\":3,\"name\":\"PUSH tag\",\"value\":\"Unused feature for pushing string\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH data\",\"value\":\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}," "{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"