mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10564 from ethereum/abiv2-isabelle-test-values
Abiv2 fuzzer: Retrieve values to be encoded from the fuzzer
This commit is contained in:
commit
6ef9ef1e15
@ -28,10 +28,28 @@ using namespace std;
|
|||||||
|
|
||||||
static constexpr size_t abiCoderHeapSize = 1024 * 512;
|
static constexpr size_t abiCoderHeapSize = 1024 * 512;
|
||||||
|
|
||||||
DEFINE_PROTO_FUZZER(Contract const&)
|
DEFINE_PROTO_FUZZER(Contract const& _contract)
|
||||||
{
|
{
|
||||||
|
ProtoConverter converter;
|
||||||
|
string contractSource = converter.contractToString(_contract);
|
||||||
|
|
||||||
|
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
|
||||||
|
{
|
||||||
|
// With libFuzzer binary run this to generate the solidity source file x.sol from a proto input:
|
||||||
|
// PROTO_FUZZER_DUMP_PATH=x.sol ./a.out proto-input
|
||||||
|
ofstream of(dump_path);
|
||||||
|
of << contractSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
string typeString = converter.isabelleTypeString();
|
||||||
|
string valueString = converter.isabelleValueString();
|
||||||
|
std::cout << typeString << std::endl;
|
||||||
|
std::cout << valueString << std::endl;
|
||||||
abicoder::ABICoder coder(abiCoderHeapSize);
|
abicoder::ABICoder coder(abiCoderHeapSize);
|
||||||
auto [encodeStatus, encodedData] = coder.encode("bool", "true");
|
if (!typeString.empty())
|
||||||
solAssert(encodeStatus, "Isabelle abicoder fuzzer: Encoding failed");
|
{
|
||||||
|
auto [encodeStatus, encodedData] = coder.encode(typeString, valueString);
|
||||||
|
solAssert(encodeStatus, "Isabelle abicoder fuzzer: Encoding failed");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
@ -32,10 +32,8 @@ message FixedByteType {
|
|||||||
required uint32 width = 1;
|
required uint32 width = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// address, address payable
|
// address
|
||||||
message AddressType {
|
message AddressType {}
|
||||||
required bool payable = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ValueType {
|
message ValueType {
|
||||||
oneof value_type_oneof {
|
oneof value_type_oneof {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <test/tools/ossfuzz/protoToAbiV2.h>
|
#include <test/tools/ossfuzz/protoToAbiV2.h>
|
||||||
|
|
||||||
#include <boost/preprocessor.hpp>
|
#include <boost/preprocessor.hpp>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
/// Convenience macros
|
/// Convenience macros
|
||||||
/// Returns a valid Solidity integer width w such that 8 <= w <= 256.
|
/// Returns a valid Solidity integer width w such that 8 <= w <= 256.
|
||||||
@ -315,6 +316,10 @@ pair<string, string> ProtoConverter::assignChecker(
|
|||||||
m_counter += acVisitor.counted();
|
m_counter += acVisitor.counted();
|
||||||
|
|
||||||
m_checks << assignCheckStrPair.second;
|
m_checks << assignCheckStrPair.second;
|
||||||
|
appendToIsabelleValueString(
|
||||||
|
acVisitor.isabelleValueString(),
|
||||||
|
((m_varCounter == 1) ? Delimiter::SKIP : Delimiter::ADD)
|
||||||
|
);
|
||||||
|
|
||||||
// State variables cannot be assigned in contract-scope
|
// State variables cannot be assigned in contract-scope
|
||||||
// Therefore, we buffer their assignments and
|
// Therefore, we buffer their assignments and
|
||||||
@ -333,12 +338,12 @@ std::string ProtoConverter::equalityChecksAsString()
|
|||||||
return m_checks.str();
|
return m_checks.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ProtoConverter::delimiterToString(Delimiter _delimiter)
|
std::string ProtoConverter::delimiterToString(Delimiter _delimiter, bool _space)
|
||||||
{
|
{
|
||||||
switch (_delimiter)
|
switch (_delimiter)
|
||||||
{
|
{
|
||||||
case Delimiter::ADD:
|
case Delimiter::ADD:
|
||||||
return ", ";
|
return _space ? ", " : ",";
|
||||||
case Delimiter::SKIP:
|
case Delimiter::SKIP:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -448,7 +453,15 @@ void ProtoConverter::appendToIsabelleTypeString(
|
|||||||
Delimiter _delimiter
|
Delimiter _delimiter
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_isabelleTypeString << delimiterToString(_delimiter) << _typeString;
|
m_isabelleTypeString << delimiterToString(_delimiter, false) << _typeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtoConverter::appendToIsabelleValueString(
|
||||||
|
std::string const& _valueString,
|
||||||
|
Delimiter _delimiter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_isabelleValueString << delimiterToString(_delimiter, false) << _valueString;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ProtoConverter::typedParametersAsString(CalleeType _calleeType)
|
std::string ProtoConverter::typedParametersAsString(CalleeType _calleeType)
|
||||||
@ -736,6 +749,15 @@ string ProtoConverter::isabelleTypeString() const
|
|||||||
return typeString;
|
return typeString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ProtoConverter::isabelleValueString() const
|
||||||
|
{
|
||||||
|
string valueString = m_isabelleValueString.str();
|
||||||
|
if (!valueString.empty())
|
||||||
|
return "(" + valueString + ")";
|
||||||
|
else
|
||||||
|
return valueString;
|
||||||
|
}
|
||||||
|
|
||||||
string ProtoConverter::contractToString(Contract const& _input)
|
string ProtoConverter::contractToString(Contract const& _input)
|
||||||
{
|
{
|
||||||
visit(_input);
|
visit(_input);
|
||||||
@ -777,9 +799,9 @@ string TypeVisitor::visit(FixedByteType const& _type)
|
|||||||
return m_baseType;
|
return m_baseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
string TypeVisitor::visit(AddressType const& _type)
|
string TypeVisitor::visit(AddressType const&)
|
||||||
{
|
{
|
||||||
m_baseType = getAddressTypeAsString(_type);
|
m_baseType = "address";
|
||||||
m_structTupleString.addTypeStringToTuple(m_baseType);
|
m_structTupleString.addTypeStringToTuple(m_baseType);
|
||||||
return m_baseType;
|
return m_baseType;
|
||||||
}
|
}
|
||||||
@ -890,33 +912,50 @@ string TypeVisitor::visit(StructType const& _type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// AssignCheckVisitor implementation
|
/// AssignCheckVisitor implementation
|
||||||
|
void AssignCheckVisitor::ValueStream::appendValue(string& _value)
|
||||||
|
{
|
||||||
|
solAssert(!_value.empty(), "Abiv2 fuzzer: Empty value");
|
||||||
|
index++;
|
||||||
|
if (index > 1)
|
||||||
|
stream << ",";
|
||||||
|
stream << _value;
|
||||||
|
}
|
||||||
|
|
||||||
pair<string, string> AssignCheckVisitor::visit(BoolType const& _type)
|
pair<string, string> AssignCheckVisitor::visit(BoolType const& _type)
|
||||||
{
|
{
|
||||||
string value = ValueGetterVisitor(counter()).visit(_type);
|
string value = ValueGetterVisitor(counter()).visit(_type);
|
||||||
|
m_valueStream.appendValue(value);
|
||||||
return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE);
|
return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<string, string> AssignCheckVisitor::visit(IntegerType const& _type)
|
pair<string, string> AssignCheckVisitor::visit(IntegerType const& _type)
|
||||||
{
|
{
|
||||||
string value = ValueGetterVisitor(counter()).visit(_type);
|
string value = ValueGetterVisitor(counter()).visit(_type);
|
||||||
|
m_valueStream.appendValue(value);
|
||||||
return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE);
|
return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<string, string> AssignCheckVisitor::visit(FixedByteType const& _type)
|
pair<string, string> AssignCheckVisitor::visit(FixedByteType const& _type)
|
||||||
{
|
{
|
||||||
string value = ValueGetterVisitor(counter()).visit(_type);
|
string value = ValueGetterVisitor(counter()).visit(_type);
|
||||||
|
string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value);
|
||||||
|
m_valueStream.appendValue(isabelleValue);
|
||||||
return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE);
|
return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<string, string> AssignCheckVisitor::visit(AddressType const& _type)
|
pair<string, string> AssignCheckVisitor::visit(AddressType const& _type)
|
||||||
{
|
{
|
||||||
string value = ValueGetterVisitor(counter()).visit(_type);
|
string value = ValueGetterVisitor(counter()).visit(_type);
|
||||||
|
string isabelleValue = ValueGetterVisitor{}.isabelleAddressValueAsString(value);
|
||||||
|
m_valueStream.appendValue(isabelleValue);
|
||||||
return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE);
|
return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<string, string> AssignCheckVisitor::visit(DynamicByteArrayType const& _type)
|
pair<string, string> AssignCheckVisitor::visit(DynamicByteArrayType const& _type)
|
||||||
{
|
{
|
||||||
string value = ValueGetterVisitor(counter()).visit(_type);
|
string value = ValueGetterVisitor(counter()).visit(_type);
|
||||||
|
string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value);
|
||||||
|
m_valueStream.appendValue(isabelleValue);
|
||||||
DataType dataType = _type.type() == DynamicByteArrayType::BYTES ? DataType::BYTES : DataType::STRING;
|
DataType dataType = _type.type() == DynamicByteArrayType::BYTES ? DataType::BYTES : DataType::STRING;
|
||||||
return assignAndCheckStringPair(m_varName, m_paramName, value, value, dataType);
|
return assignAndCheckStringPair(m_varName, m_paramName, value, value, dataType);
|
||||||
}
|
}
|
||||||
@ -981,6 +1020,7 @@ pair<string, string> AssignCheckVisitor::visit(ArrayType const& _type)
|
|||||||
pair<string, string> assignCheckBuffer;
|
pair<string, string> assignCheckBuffer;
|
||||||
string wasVarName = m_varName;
|
string wasVarName = m_varName;
|
||||||
string wasParamName = m_paramName;
|
string wasParamName = m_paramName;
|
||||||
|
m_valueStream.startArray();
|
||||||
for (unsigned i = 0; i < length; i++)
|
for (unsigned i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
m_varName = wasVarName + "[" + to_string(i) + "]";
|
m_varName = wasVarName + "[" + to_string(i) + "]";
|
||||||
@ -991,6 +1031,7 @@ pair<string, string> AssignCheckVisitor::visit(ArrayType const& _type)
|
|||||||
if (i < length - 1)
|
if (i < length - 1)
|
||||||
m_structCounter = wasStructCounter;
|
m_structCounter = wasStructCounter;
|
||||||
}
|
}
|
||||||
|
m_valueStream.endArray();
|
||||||
|
|
||||||
// Since struct visitor won't be called for zero-length
|
// Since struct visitor won't be called for zero-length
|
||||||
// arrays, struct counter will not get incremented. Therefore,
|
// arrays, struct counter will not get incremented. Therefore,
|
||||||
@ -1022,6 +1063,7 @@ pair<string, string> AssignCheckVisitor::visit(StructType const& _type)
|
|||||||
string wasVarName = m_varName;
|
string wasVarName = m_varName;
|
||||||
string wasParamName = m_paramName;
|
string wasParamName = m_paramName;
|
||||||
|
|
||||||
|
m_valueStream.startStruct();
|
||||||
for (auto const& t: _type.t())
|
for (auto const& t: _type.t())
|
||||||
{
|
{
|
||||||
m_varName = wasVarName + ".m" + to_string(i);
|
m_varName = wasVarName + ".m" + to_string(i);
|
||||||
@ -1035,6 +1077,7 @@ pair<string, string> AssignCheckVisitor::visit(StructType const& _type)
|
|||||||
assignCheckBuffer.second += assign.second;
|
assignCheckBuffer.second += assign.second;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
m_valueStream.endStruct();
|
||||||
m_varName = wasVarName;
|
m_varName = wasVarName;
|
||||||
m_paramName = wasParamName;
|
m_paramName = wasParamName;
|
||||||
return assignCheckBuffer;
|
return assignCheckBuffer;
|
||||||
@ -1117,11 +1160,11 @@ string ValueGetterVisitor::visit(AddressType const&)
|
|||||||
return addressValueAsString(counter());
|
return addressValueAsString(counter());
|
||||||
}
|
}
|
||||||
|
|
||||||
string ValueGetterVisitor::visit(DynamicByteArrayType const& _type)
|
string ValueGetterVisitor::visit(DynamicByteArrayType const&)
|
||||||
{
|
{
|
||||||
return bytesArrayValueAsString(
|
return bytesArrayValueAsString(
|
||||||
counter(),
|
counter(),
|
||||||
getDataTypeOfDynBytesType(_type) == DataType::BYTES
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1195,10 +1238,29 @@ std::string ValueGetterVisitor::fixedByteValueAsString(unsigned _width, unsigned
|
|||||||
|
|
||||||
std::string ValueGetterVisitor::addressValueAsString(unsigned _counter)
|
std::string ValueGetterVisitor::addressValueAsString(unsigned _counter)
|
||||||
{
|
{
|
||||||
// TODO: Isabelle encoder expects address literal to be exactly
|
return "address(" + maskUnsignedIntToHex(_counter, 40) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ValueGetterVisitor::isabelleAddressValueAsString(std::string& _solAddressString)
|
||||||
|
{
|
||||||
|
// Isabelle encoder expects address literal to be exactly
|
||||||
// 20 bytes and a hex string.
|
// 20 bytes and a hex string.
|
||||||
// Example: 0x0102030405060708090a0102030405060708090a
|
// Example: 0x0102030405060708090a0102030405060708090a
|
||||||
return "address(" + maskUnsignedIntToHex(_counter, 40) + ")";
|
std::regex const addressPattern("address\\((.*)\\)");
|
||||||
|
std::smatch match;
|
||||||
|
solAssert(std::regex_match(_solAddressString, match, addressPattern), "Abiv2 fuzzer: Invalid address string");
|
||||||
|
std::string addressHex = match[1].str();
|
||||||
|
addressHex.erase(2, 24);
|
||||||
|
return addressHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ValueGetterVisitor::isabelleBytesValueAsString(std::string& _solBytesString)
|
||||||
|
{
|
||||||
|
std::regex const bytesPattern("hex\"(.*)\"");
|
||||||
|
std::smatch match;
|
||||||
|
solAssert(std::regex_match(_solBytesString, match, bytesPattern), "Abiv2 fuzzer: Invalid bytes string");
|
||||||
|
std::string bytesHex = match[1].str();
|
||||||
|
return "0x" + bytesHex;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ValueGetterVisitor::variableLengthValueAsString(
|
std::string ValueGetterVisitor::variableLengthValueAsString(
|
||||||
|
@ -153,6 +153,7 @@ public:
|
|||||||
ProtoConverter(ProtoConverter&&) = delete;
|
ProtoConverter(ProtoConverter&&) = delete;
|
||||||
std::string contractToString(Contract const& _input);
|
std::string contractToString(Contract const& _input);
|
||||||
std::string isabelleTypeString() const;
|
std::string isabelleTypeString() const;
|
||||||
|
std::string isabelleValueString() const;
|
||||||
private:
|
private:
|
||||||
enum class Delimiter
|
enum class Delimiter
|
||||||
{
|
{
|
||||||
@ -295,6 +296,13 @@ private:
|
|||||||
Delimiter _delimiter
|
Delimiter _delimiter
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Append @a _valueString to value string meant to be
|
||||||
|
/// passed to Isabelle coder API.
|
||||||
|
void appendToIsabelleValueString(
|
||||||
|
std::string const& _valueString,
|
||||||
|
Delimiter _delimiter
|
||||||
|
);
|
||||||
|
|
||||||
/// Returns a Solidity variable declaration statement
|
/// Returns a Solidity variable declaration statement
|
||||||
/// @param _type: string containing Solidity type of the
|
/// @param _type: string containing Solidity type of the
|
||||||
/// variable to be declared.
|
/// variable to be declared.
|
||||||
@ -367,7 +375,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert delimter to a comma or null string.
|
/// Convert delimter to a comma or null string.
|
||||||
static std::string delimiterToString(Delimiter _delimiter);
|
static std::string delimiterToString(Delimiter _delimiter, bool _space = true);
|
||||||
|
|
||||||
/// Contains the test program
|
/// Contains the test program
|
||||||
std::ostringstream m_output;
|
std::ostringstream m_output;
|
||||||
@ -379,6 +387,9 @@ private:
|
|||||||
std::ostringstream m_typedParamsPublic;
|
std::ostringstream m_typedParamsPublic;
|
||||||
/// Contains type string to be passed to Isabelle API
|
/// Contains type string to be passed to Isabelle API
|
||||||
std::ostringstream m_isabelleTypeString;
|
std::ostringstream m_isabelleTypeString;
|
||||||
|
/// Contains values to be encoded in the format accepted
|
||||||
|
/// by the Isabelle API.
|
||||||
|
std::ostringstream m_isabelleValueString;
|
||||||
/// Contains type stream to be used in returndata coder function
|
/// Contains type stream to be used in returndata coder function
|
||||||
/// signature
|
/// signature
|
||||||
std::ostringstream m_types;
|
std::ostringstream m_types;
|
||||||
@ -476,19 +487,6 @@ public:
|
|||||||
return "bytes" + std::to_string(getFixedByteWidth(_x));
|
return "bytes" + std::to_string(getFixedByteWidth(_x));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getAddressTypeAsString(AddressType const& _x)
|
|
||||||
{
|
|
||||||
return (_x.payable() ? "address payable" : "address");
|
|
||||||
}
|
|
||||||
|
|
||||||
static DataType getDataTypeOfDynBytesType(DynamicByteArrayType const& _x)
|
|
||||||
{
|
|
||||||
if (_x.type() == DynamicByteArrayType::STRING)
|
|
||||||
return DataType::STRING;
|
|
||||||
else
|
|
||||||
return DataType::BYTES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert _counter to string and return its keccak256 hash
|
// Convert _counter to string and return its keccak256 hash
|
||||||
static u256 hashUnsignedInt(unsigned _counter)
|
static u256 hashUnsignedInt(unsigned _counter)
|
||||||
{
|
{
|
||||||
@ -531,7 +529,13 @@ public:
|
|||||||
// this linear equation to make the number derived from
|
// this linear equation to make the number derived from
|
||||||
// _counter approach a uniform distribution over
|
// _counter approach a uniform distribution over
|
||||||
// [0, s_maxDynArrayLength]
|
// [0, s_maxDynArrayLength]
|
||||||
return (_counter + 879) * 32 % (s_maxDynArrayLength + 1);
|
auto v = (_counter + 879) * 32 % (s_maxDynArrayLength + 1);
|
||||||
|
/// Always return an even number because Isabelle string
|
||||||
|
/// values are formatted as hex literals
|
||||||
|
if (v % 2 == 1)
|
||||||
|
return v + 1;
|
||||||
|
else
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string bytesArrayTypeAsString(DynamicByteArrayType const& _x)
|
static std::string bytesArrayTypeAsString(DynamicByteArrayType const& _x)
|
||||||
@ -658,10 +662,6 @@ private:
|
|||||||
{
|
{
|
||||||
stream << ")";
|
stream << ")";
|
||||||
}
|
}
|
||||||
std::string operator()()
|
|
||||||
{
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
void addTypeStringToTuple(std::string& _typeString);
|
void addTypeStringToTuple(std::string& _typeString);
|
||||||
void addArrayBracketToType(std::string& _arrayBracket);
|
void addArrayBracketToType(std::string& _arrayBracket);
|
||||||
};
|
};
|
||||||
@ -735,7 +735,35 @@ public:
|
|||||||
{
|
{
|
||||||
return m_structCounter - m_structStart;
|
return m_structCounter - m_structStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string isabelleValueString()
|
||||||
|
{
|
||||||
|
return m_valueStream.stream.str();
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
|
struct ValueStream
|
||||||
|
{
|
||||||
|
ValueStream() = default;
|
||||||
|
unsigned index = 0;
|
||||||
|
std::ostringstream stream;
|
||||||
|
void startStruct()
|
||||||
|
{
|
||||||
|
stream << "(";
|
||||||
|
}
|
||||||
|
void endStruct()
|
||||||
|
{
|
||||||
|
stream << ")";
|
||||||
|
}
|
||||||
|
void startArray()
|
||||||
|
{
|
||||||
|
stream << "[";
|
||||||
|
}
|
||||||
|
void endArray()
|
||||||
|
{
|
||||||
|
stream << "]";
|
||||||
|
}
|
||||||
|
void appendValue(std::string& _value);
|
||||||
|
};
|
||||||
std::string indentation()
|
std::string indentation()
|
||||||
{
|
{
|
||||||
return std::string(m_indentation * 1, '\t');
|
return std::string(m_indentation * 1, '\t');
|
||||||
@ -764,6 +792,7 @@ private:
|
|||||||
bool m_stateVar;
|
bool m_stateVar;
|
||||||
unsigned m_structCounter;
|
unsigned m_structCounter;
|
||||||
unsigned m_structStart;
|
unsigned m_structStart;
|
||||||
|
ValueStream m_valueStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns a valid value (as a string) for a given type.
|
/// Returns a valid value (as a string) for a given type.
|
||||||
@ -786,6 +815,8 @@ public:
|
|||||||
solAssert(false, "ABIv2 proto fuzzer: Cannot call valuegettervisitor on complex type");
|
solAssert(false, "ABIv2 proto fuzzer: Cannot call valuegettervisitor on complex type");
|
||||||
}
|
}
|
||||||
using AbiV2ProtoVisitor<std::string>::visit;
|
using AbiV2ProtoVisitor<std::string>::visit;
|
||||||
|
static std::string isabelleAddressValueAsString(std::string& _solAddressString);
|
||||||
|
static std::string isabelleBytesValueAsString(std::string& _solFixedBytesString);
|
||||||
private:
|
private:
|
||||||
unsigned counter()
|
unsigned counter()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user