diff --git a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz index 787b33c03..2b1bef899 100644 --- a/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz @@ -22,7 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang as base -LABEL version="6" +LABEL version="7" ARG DEBIAN_FRONTEND=noninteractive @@ -32,7 +32,7 @@ RUN apt-get update; \ software-properties-common \ ninja-build git wget \ libbz2-dev zlib1g-dev git curl uuid-dev \ - pkg-config openjdk-8-jdk liblzma-dev unzip mlton; \ + pkg-config openjdk-8-jdk liblzma-dev unzip mlton m4; \ apt-get install -qy python-pip python-sphinx; # Install cmake 3.14 (minimum requirement is cmake 3.10) @@ -113,6 +113,25 @@ RUN set -ex; \ ninja install/strip; \ rm -rf /usr/src/hera +# gmp +RUN set -ex; \ + # Replace system installed libgmp static library + # with sanitized version. Do not perform apt + # remove because it removes mlton as well that + # we need for building libabicoder + rm -f /usr/lib/x86_64-linux-gnu/libgmp.*; \ + rm -f /usr/include/x86_64-linux-gnu/gmp.h; \ + cd /usr/src; \ + wget -q 'https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz' -O gmp.tar.xz; \ + test "$(sha256sum gmp.tar.xz)" = "fd4829912cddd12f84181c3451cc752be224643e87fac497b69edddadc49b4f2 gmp.tar.xz"; \ + tar -xf gmp.tar.xz; \ + cd gmp-6.2.1; \ + ./configure --prefix=/usr --enable-static=yes; \ + make -j; \ + make install; \ + rm -rf /usr/src/gmp-6.2.1; \ + rm -f /usr/src/gmp.tar.xz + # libabicoder RUN set -ex; \ cd /usr/src; \ @@ -127,5 +146,4 @@ RUN set -ex; \ FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin -COPY --from=libraries /usr/include /usr/include - +COPY --from=libraries /usr/include /usr/include \ No newline at end of file diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index a55ed68c9..a88c14581 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -51,9 +51,11 @@ AnalysisFramework::parseAnalyseAndReturnError( ) { compiler().reset(); + // Do not insert license if it is already present. + bool insertLicense = _insertLicenseAndVersionPragma && _source.find("// SPDX-License-Identifier:") == string::npos; compiler().setSources({{"", - _insertLicenseAndVersionPragma ? - "pragma solidity >=0.0;\n// SPDX-License-Identifier: GPL-3.0\n" + _source : + string{_insertLicenseAndVersionPragma ? "pragma solidity >=0.0;\n" : ""} + + string{insertLicense ? "// SPDX-License-Identifier: GPL-3.0\n" : ""} + _source }}); compiler().setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 9f6c28043..ab0bba27d 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -134,7 +134,9 @@ bytes SolidityExecutionFramework::compileContract( string SolidityExecutionFramework::addPreamble(string const& _sourceCode) { // Silence compiler version warning - string preamble = "pragma solidity >=0.0;\n// SPDX-License-Identifier: unlicensed\n"; + string preamble = "pragma solidity >=0.0;\n"; + if (_sourceCode.find("// SPDX-License-Identifier:") == string::npos) + preamble += "// SPDX-License-Identifier: unlicensed\n"; if ( solidity::test::CommonOptions::get().useABIEncoderV1 && _sourceCode.find("pragma experimental ABIEncoderV2;") == string::npos && diff --git a/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol new file mode 100644 index 000000000..6f380ebee --- /dev/null +++ b/test/libsolidity/semanticTests/externalContracts/deposit_contract.sol @@ -0,0 +1,196 @@ +// ┏━━━┓━┏┓━┏┓━━┏━━━┓━━┏━━━┓━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━┏┓━━━━━┏━━━┓━━━━━━━━━┏┓━━━━━━━━━━━━━━┏┓━ +// ┃┏━━┛┏┛┗┓┃┃━━┃┏━┓┃━━┃┏━┓┃━━━━┗┓┏┓┃━━━━━━━━━━━━━━━━━━┏┛┗┓━━━━┃┏━┓┃━━━━━━━━┏┛┗┓━━━━━━━━━━━━┏┛┗┓ +// ┃┗━━┓┗┓┏┛┃┗━┓┗┛┏┛┃━━┃┃━┃┃━━━━━┃┃┃┃┏━━┓┏━━┓┏━━┓┏━━┓┏┓┗┓┏┛━━━━┃┃━┗┛┏━━┓┏━┓━┗┓┏┛┏━┓┏━━┓━┏━━┓┗┓┏┛ +// ┃┏━━┛━┃┃━┃┏┓┃┏━┛┏┛━━┃┃━┃┃━━━━━┃┃┃┃┃┏┓┃┃┏┓┃┃┏┓┃┃━━┫┣┫━┃┃━━━━━┃┃━┏┓┃┏┓┃┃┏┓┓━┃┃━┃┏┛┗━┓┃━┃┏━┛━┃┃━ +// ┃┗━━┓━┃┗┓┃┃┃┃┃┃┗━┓┏┓┃┗━┛┃━━━━┏┛┗┛┃┃┃━┫┃┗┛┃┃┗┛┃┣━━┃┃┃━┃┗┓━━━━┃┗━┛┃┃┗┛┃┃┃┃┃━┃┗┓┃┃━┃┗┛┗┓┃┗━┓━┃┗┓ +// ┗━━━┛━┗━┛┗┛┗┛┗━━━┛┗┛┗━━━┛━━━━┗━━━┛┗━━┛┃┏━┛┗━━┛┗━━┛┗┛━┗━┛━━━━┗━━━┛┗━━┛┗┛┗┛━┗━┛┗┛━┗━━━┛┗━━┛━┗━┛ +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┃┃━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┗┛━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +// SPDX-License-Identifier: CC0-1.0 + +// This interface is designed to be compatible with the Vyper version. +/// @notice This is the Ethereum 2.0 deposit contract interface. +/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs +interface IDepositContract { + /// @notice A processed deposit event. + event DepositEvent( + bytes pubkey, + bytes withdrawal_credentials, + bytes amount, + bytes signature, + bytes index + ); + + /// @notice Submit a Phase 0 DepositData object. + /// @param pubkey A BLS12-381 public key. + /// @param withdrawal_credentials Commitment to a public key for withdrawals. + /// @param signature A BLS12-381 signature. + /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object. + /// Used as a protection against malformed input. + function deposit( + bytes calldata pubkey, + bytes calldata withdrawal_credentials, + bytes calldata signature, + bytes32 deposit_data_root + ) external payable; + + /// @notice Query the current deposit root hash. + /// @return The deposit root hash. + function get_deposit_root() external view returns (bytes32); + + /// @notice Query the current deposit count. + /// @return The deposit count encoded as a little endian 64-bit number. + function get_deposit_count() external view returns (bytes memory); +} + +// Based on official specification in https://eips.ethereum.org/EIPS/eip-165 +interface ERC165 { + /// @notice Query if a contract implements an interface + /// @param interfaceId The interface identifier, as specified in ERC-165 + /// @dev Interface identification is specified in ERC-165. This function + /// uses less than 30,000 gas. + /// @return `true` if the contract implements `interfaceId` and + /// `interfaceId` is not 0xffffffff, `false` otherwise + function supportsInterface(bytes4 interfaceId) external pure returns (bool); +} + +// This is a rewrite of the Vyper Eth2.0 deposit contract in Solidity. +// It tries to stay as close as possible to the original source code. +/// @notice This is the Ethereum 2.0 deposit contract interface. +/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs +contract DepositContract is IDepositContract, ERC165 { + uint constant DEPOSIT_CONTRACT_TREE_DEPTH = 32; + // NOTE: this also ensures `deposit_count` will fit into 64-bits + uint constant MAX_DEPOSIT_COUNT = 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1; + + bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] branch; + uint256 deposit_count; + + bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] zero_hashes; + + constructor() public { + // Compute hashes in empty sparse Merkle tree + for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH - 1; height++) + zero_hashes[height + 1] = sha256(abi.encodePacked(zero_hashes[height], zero_hashes[height])); + } + + function get_deposit_root() override external view returns (bytes32) { + bytes32 node; + uint size = deposit_count; + for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) { + if ((size & 1) == 1) + node = sha256(abi.encodePacked(branch[height], node)); + else + node = sha256(abi.encodePacked(node, zero_hashes[height])); + size /= 2; + } + return sha256(abi.encodePacked( + node, + to_little_endian_64(uint64(deposit_count)), + bytes24(0) + )); + } + + function get_deposit_count() override external view returns (bytes memory) { + return to_little_endian_64(uint64(deposit_count)); + } + + function deposit( + bytes calldata pubkey, + bytes calldata withdrawal_credentials, + bytes calldata signature, + bytes32 deposit_data_root + ) override external payable { + // Extended ABI length checks since dynamic types are used. + require(pubkey.length == 48, "DepositContract: invalid pubkey length"); + require(withdrawal_credentials.length == 32, "DepositContract: invalid withdrawal_credentials length"); + require(signature.length == 96, "DepositContract: invalid signature length"); + + // Check deposit amount + require(msg.value >= 1 ether, "DepositContract: deposit value too low"); + require(msg.value % 1 gwei == 0, "DepositContract: deposit value not multiple of gwei"); + uint deposit_amount = msg.value / 1 gwei; + require(deposit_amount <= type(uint64).max, "DepositContract: deposit value too high"); + + // Emit `DepositEvent` log + bytes memory amount = to_little_endian_64(uint64(deposit_amount)); + emit DepositEvent( + pubkey, + withdrawal_credentials, + amount, + signature, + to_little_endian_64(uint64(deposit_count)) + ); + + // Compute deposit data root (`DepositData` hash tree root) + bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0))); + bytes32 signature_root = sha256(abi.encodePacked( + sha256(abi.encodePacked(signature[:64])), + sha256(abi.encodePacked(signature[64:], bytes32(0))) + )); + bytes32 node = sha256(abi.encodePacked( + sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)), + sha256(abi.encodePacked(amount, bytes24(0), signature_root)) + )); + + // Verify computed and expected deposit data roots match + require(node == deposit_data_root, "DepositContract: reconstructed DepositData does not match supplied deposit_data_root"); + + // Avoid overflowing the Merkle tree (and prevent edge case in computing `branch`) + require(deposit_count < MAX_DEPOSIT_COUNT, "DepositContract: merkle tree full"); + + // Add deposit data root to Merkle tree (update a single `branch` node) + deposit_count += 1; + uint size = deposit_count; + for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) { + if ((size & 1) == 1) { + branch[height] = node; + return; + } + node = sha256(abi.encodePacked(branch[height], node)); + size /= 2; + } + // As the loop should always end prematurely with the `return` statement, + // this code should be unreachable. We assert `false` just to be safe. + assert(false); + } + + function supportsInterface(bytes4 interfaceId) override external pure returns (bool) { + return interfaceId == type(ERC165).interfaceId || interfaceId == type(IDepositContract).interfaceId; + } + + function to_little_endian_64(uint64 value) internal pure returns (bytes memory ret) { + ret = new bytes(8); + bytes8 bytesValue = bytes8(value); + // Byteswapping during copying to bytes. + ret[0] = bytesValue[7]; + ret[1] = bytesValue[6]; + ret[2] = bytesValue[5]; + ret[3] = bytesValue[4]; + ret[4] = bytesValue[3]; + ret[5] = bytesValue[2]; + ret[6] = bytesValue[1]; + ret[7] = bytesValue[0]; + } +} +// ==== +// compileViaYul: also +// ---- +// constructor() +// supportsInterface(bytes4): 0x0 -> 0 +// supportsInterface(bytes4): 0xffffffff00000000000000000000000000000000000000000000000000000000 -> false # defined to be false by ERC-165 # +// supportsInterface(bytes4): 0x01ffc9a700000000000000000000000000000000000000000000000000000000 -> true # ERC-165 id # +// supportsInterface(bytes4): 0x8564090700000000000000000000000000000000000000000000000000000000 -> true # the deposit interface id # +// get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e +// get_deposit_count() -> 0x20, 8, 0 +// # TODO: check balance and logs after each deposit # +// deposit(bytes,bytes,bytes,bytes32), 32 ether: 0 -> FAILURE # Empty input # +// get_deposit_root() -> 0xd70a234731285c6804c2a4f56711ddb8c82c99740f207854891028af34e27e5e +// get_deposit_count() -> 0x20, 8, 0 +// deposit(bytes,bytes,bytes,bytes32), 1 ether: 0x80, 0xe0, 0x120, 0xaa4a8d0b7d9077248630f1a4701ae9764e42271d7f22b7838778411857fd349e, 0x30, 0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f73292, 0x67a8811c397529dac52ae1342ba58c9500000000000000000000000000000000, 0x20, 0x00f50428677c60f997aadeab24aabf7fceaef491c96a52b463ae91f95611cf71, 0x60, 0xa29d01cc8c6296a8150e515b5995390ef841dc18948aa3e79be6d7c1851b4cbb, 0x5d6ff49fa70b9c782399506a22a85193151b9b691245cebafd2063012443c132, 0x4b6c36debaedefb7b2d71b0503ffdc00150aaffd42e63358238ec888901738b8 -> # txhash: 0x7085c586686d666e8bb6e9477a0f0b09565b2060a11f1c4209d3a52295033832 # +// get_deposit_root() -> 0x2089653123d9c721215120b6db6738ba273bbc5228ac093b1f983badcdc8a438 +// get_deposit_count() -> 0x20, 8, 0x0100000000000000000000000000000000000000000000000000000000000000 +// deposit(bytes,bytes,bytes,bytes32), 32 ether: 0x80, 0xe0, 0x120, 0xdbd986dc85ceb382708cf90a3500f500f0a393c5ece76963ac3ed72eccd2c301, 0x30, 0xb2ce0f79f90e7b3a113ca5783c65756f96c4b4673c2b5c1eb4efc22280259441, 0x06d601211e8866dc5b50dc48a244dd7c00000000000000000000000000000000, 0x20, 0x00344b6c73f71b11c56aba0d01b7d8ad83559f209d0a4101a515f6ad54c89771, 0x60, 0x945caaf82d18e78c033927d51f452ebcd76524497b91d7a11219cb3db6a1d369, 0x7595fc095ce489e46b2ef129591f2f6d079be4faaf345a02c5eb133c072e7c56, 0x0c6c3617eee66b4b878165c502357d49485326bc6b31bc96873f308c8f19c09d -> # txhash: 0x404d8e109822ce448e68f45216c12cb051b784d068fbe98317ab8e50c58304ac # +// get_deposit_root() -> 0x40255975859377d912c53aa853245ebd939bdd2b33a28e084babdcc1ed8238ee +// get_deposit_count() -> 0x20, 8, 0x0200000000000000000000000000000000000000000000000000000000000000 diff --git a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp index 87b7fd913..4d9989012 100644 --- a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp +++ b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp @@ -24,9 +24,14 @@ using namespace solidity::test::abiv2fuzzer; using namespace solidity::test; +using namespace solidity::util; +using namespace solidity; using namespace std; static constexpr size_t abiCoderHeapSize = 1024 * 512; +static evmc::VM evmone = evmc::VM{evmc_create_evmone()}; +/// Expected output value is decimal 0 +static vector const expectedOutput(32, 0); DEFINE_PROTO_FUZZER(Contract const& _contract) { @@ -43,13 +48,60 @@ DEFINE_PROTO_FUZZER(Contract const& _contract) string typeString = converter.isabelleTypeString(); string valueString = converter.isabelleValueString(); - std::cout << typeString << std::endl; - std::cout << valueString << std::endl; abicoder::ABICoder coder(abiCoderHeapSize); - if (!typeString.empty()) + if (!typeString.empty() && converter.coderFunction()) { auto [encodeStatus, encodedData] = coder.encode(typeString, valueString); solAssert(encodeStatus, "Isabelle abicoder fuzzer: Encoding failed"); + + // Raw runtime byte code generated by solidity + bytes byteCode; + string hexEncodedInput; + + try + { + // Compile contract generated by the proto fuzzer + SolidityCompilationFramework solCompilationFramework; + string contractName = ":C"; + byteCode = solCompilationFramework.compileContract(contractSource, contractName); + Json::Value methodIdentifiers = solCompilationFramework.getMethodIdentifiers(); + // We always call the second function from the list of alphabetically + // sorted interface functions + hexEncodedInput = (++methodIdentifiers.begin())->asString() + encodedData.substr(2, encodedData.size()); + } + // Ignore stack too deep errors during compilation + catch (solidity::evmasm::StackTooDeepException const&) + { + return; + } + + // We target the default EVM which is the latest + solidity::langutil::EVMVersion version; + EVMHost hostContext(version, evmone); + + // Deploy contract and signal failure if deployment failed + evmc::result createResult = AbiV2Utility::deployContract(hostContext, byteCode); + solAssert( + createResult.status_code == EVMC_SUCCESS, + "Proto ABIv2 Fuzzer: Contract creation failed" + ); + + // Execute test function and signal failure if EVM reverted or + // did not return expected output on successful execution. + evmc::result callResult = AbiV2Utility::executeContract( + hostContext, + fromHex(hexEncodedInput), + createResult.create_address + ); + + // We don't care about EVM One failures other than EVMC_REVERT + solAssert(callResult.status_code != EVMC_REVERT, "Proto ABIv2 fuzzer: EVM One reverted"); + if (callResult.status_code == EVMC_SUCCESS) + solAssert( + AbiV2Utility::isOutputExpected(callResult.output_data, callResult.output_size, expectedOutput), + "Proto ABIv2 fuzzer: ABIv2 coding failure found" + ); + } return; } diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt index 3d205722b..21d1e19dc 100644 --- a/test/tools/ossfuzz/CMakeLists.txt +++ b/test/tools/ossfuzz/CMakeLists.txt @@ -151,7 +151,7 @@ if (OSSFUZZ) protobuf-mutator.a protobuf.a abicoder - gmp + gmp.a ) set_target_properties(abiv2_isabelle_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) target_compile_options(abiv2_isabelle_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override) diff --git a/test/tools/ossfuzz/abiV2Proto.proto b/test/tools/ossfuzz/abiV2Proto.proto index 886ca53f7..1afc03176 100644 --- a/test/tools/ossfuzz/abiV2Proto.proto +++ b/test/tools/ossfuzz/abiV2Proto.proto @@ -44,14 +44,8 @@ message ValueType { } } -// bytes/string -message DynamicByteArrayType { - enum DType { - BYTES = 0; - STRING = 1; - } - required DType type = 1; -} +// bytes +message DynamicByteArrayType {} message ArrayType { required Type t = 1; diff --git a/test/tools/ossfuzz/protoToAbiV2.cpp b/test/tools/ossfuzz/protoToAbiV2.cpp index 4e5b2081a..47d3942bb 100644 --- a/test/tools/ossfuzz/protoToAbiV2.cpp +++ b/test/tools/ossfuzz/protoToAbiV2.cpp @@ -69,7 +69,7 @@ static V integerValue(unsigned _counter) V value = V( u256(solidity::util::keccak256(solidity::util::h256(_counter))) % u256(boost::math::tools::max_value()) ); - if (value % 2 == 0) + if (boost::multiprecision::is_signed_number::value && value % 2 == 0) return value * (-1); else return value; @@ -830,10 +830,10 @@ string TypeVisitor::visit(ArrayType const& _type) return baseType + arrayBracket; } -string TypeVisitor::visit(DynamicByteArrayType const& _type) +string TypeVisitor::visit(DynamicByteArrayType const&) { m_isLastDynParamRightPadded = true; - m_baseType = bytesArrayTypeAsString(_type); + m_baseType = "bytes"; m_structTupleString.addTypeStringToTuple(m_baseType); return m_baseType; } @@ -967,7 +967,7 @@ pair AssignCheckVisitor::visit(DynamicByteArrayType const& _type string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); m_valueStream.appendValue(isabelleValue); } - DataType dataType = _type.type() == DynamicByteArrayType::BYTES ? DataType::BYTES : DataType::STRING; + DataType dataType = DataType::BYTES; return assignAndCheckStringPair(m_varName, m_paramName, value, value, dataType); } @@ -1127,12 +1127,6 @@ string AssignCheckVisitor::checkString(string const& _ref, string const& _value, string checkPred; switch (_type) { - case DataType::STRING: - checkPred = Whiskers(R"(!bytesCompare(bytes(), ))") - ("varName", _ref) - ("value", _value) - .render(); - break; case DataType::BYTES: checkPred = Whiskers(R"(!bytesCompare(, ))") ("varName", _ref) @@ -1288,10 +1282,6 @@ std::string ValueGetterVisitor::variableLengthValueAsString( bool _isHexLiteral ) { - // TODO: Move this to caller -// solAssert(_numBytes >= 0 && _numBytes <= s_maxDynArrayLength, -// "Proto ABIv2 fuzzer: Invalid hex length" -// ); if (_numBytes == 0) return Whiskers(R"(hex"")") ("isHex", _isHexLiteral) diff --git a/test/tools/ossfuzz/protoToAbiV2.h b/test/tools/ossfuzz/protoToAbiV2.h index 4d7421de4..a2be558e8 100644 --- a/test/tools/ossfuzz/protoToAbiV2.h +++ b/test/tools/ossfuzz/protoToAbiV2.h @@ -154,6 +154,10 @@ public: std::string contractToString(Contract const& _input); std::string isabelleTypeString() const; std::string isabelleValueString() const; + bool coderFunction() const + { + return m_test == Contract_Test::Contract_Test_CALLDATA_CODER; + } private: enum class Delimiter { @@ -448,7 +452,6 @@ public: enum class DataType { BYTES, - STRING, VALUE, ARRAY }; @@ -537,17 +540,6 @@ public: else return v; } - - static std::string bytesArrayTypeAsString(DynamicByteArrayType const& _x) - { - switch (_x.type()) - { - case DynamicByteArrayType::BYTES: - return "bytes"; - case DynamicByteArrayType::STRING: - return "string"; - } - } protected: T visitValueType(ValueType const& _type) {