Merge pull request #10096 from ethereum/pragmaabicoder

Introduce abicoder pragma.
This commit is contained in:
chriseth 2020-11-03 13:53:59 +01:00 committed by GitHub
commit 4e6ae00f89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 196 additions and 111 deletions

View File

@ -1,5 +1,8 @@
### 0.7.5 (unreleased)
Language Features:
* Ability to select the abi coder using ``pragma abicoder v1`` and ``pragma abicoder v2``.
Compiler Features:
* SMTChecker: Add division by zero checks in the CHC engine.
* SMTChecker: Support ``selector`` for expressions with value known at compile-time.

View File

@ -132,7 +132,7 @@ Yul Optimizer
Together with the legacy bytecode optimizer, the :doc:`Yul <yul>` optimizer is now enabled by default when you call the compiler
with ``--optimize``. It can be disabled by calling the compiler with ``--no-optimize-yul``.
This mostly affects code that uses ABIEncoderV2.
This mostly affects code that uses ABI coder v2.
C API Changes
~~~~~~~~~~~~~

View File

@ -589,8 +589,8 @@ As an example, the code
::
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.19 <0.8.0;
pragma experimental ABIEncoderV2;
pragma solidity >0.7.4;
pragma abicoder v2;
contract Test {
struct S { uint a; uint[] b; T[] c; }

View File

@ -67,8 +67,8 @@ Function parameters can be used as any other local variable and they can also be
An :ref:`external function<external-function-calls>` cannot accept a
multi-dimensional array as an input
parameter. This functionality is possible if you enable the new
``ABIEncoderV2`` feature by adding ``pragma experimental ABIEncoderV2;`` to your source file.
parameter. This functionality is possible if you enable the ABI coder v2
by adding ``pragma abicoder v2;`` to your source file.
An :ref:`internal function<external-function-calls>` can accept a
multi-dimensional array without enabling the feature.
@ -128,8 +128,8 @@ you must provide return values together with the return statement.
.. note::
You cannot return some types from non-internal functions, notably
multi-dimensional dynamic arrays and structs. If you enable the
new ``ABIEncoderV2`` feature by adding ``pragma experimental
ABIEncoderV2;`` to your source file then more types are available, but
ABI coder v2 by adding ``pragma abicoder v2;``
to your source file then more types are available, but
``mapping`` types are still limited to inside a single contract and you
cannot transfer them.

View File

@ -88,6 +88,41 @@ these follow the same syntax used by `npm <https://docs.npmjs.com/misc/semver>`_
required by the pragma. If it does not match, the compiler issues
an error.
ABI Coder Pragma
----------------
By using ``pragma abicoder v1`` or ``pragma abicoder v2`` you can
select between the two implementations of the ABI encoder and decoder.
The new ABI coder (v2) is able to encode and decode arbitrarily nested
arrays and structs. It might produce less optimal code and has not
received as much testing as the old encoder, but is considered
non-experimental as of Solidity 0.6.0. You still have to explicitly
activate it using ``pragma abicoder v2;``. Since it will be
activated by default starting from Solidity 0.8.0, there is the option to select
the old coder using ``pragma abicoder v1;``.
The set of types supported by the new encoder is a strict superset of
the ones supported by the old one. Contracts that use it can interact with ones
that do not without limitations. The reverse is possible only as long as the
non-``abicoder v2`` contract does not try to make calls that would require
decoding types only supported by the new encoder. The compiler can detect this
and will issue an error. Simply enabling ``abicoder v2`` for your contract is
enough to make the error go away.
.. note::
This pragma applies to all the code defined in the file where it is activated,
regardless of where that code ends up eventually. This means that a contract
whose source file is selected to compile with ABI coder v1
can still contain code that uses the new encoder
by inheriting it from another contract. This is allowed if the new types are only
used internally and not in external function signatures.
.. note::
Up to Solidity 0.7.4, it was possible to select the ABI coder v2
by using ``pragma experimental ABIEncoderV2``, but it was not possible
to explicitly select coder v1 because it was the default.
.. index:: ! pragma, experimental
.. _experimental_pragma:
@ -103,28 +138,9 @@ The following experimental pragmas are currently supported:
ABIEncoderV2
~~~~~~~~~~~~
The new ABI encoder is able to encode and decode arbitrarily nested
arrays and structs. It might produce less optimal code and has not
received as much testing as the old encoder, but is considered
non-experimental as of Solidity 0.6.0. You still have to explicitly
activate it using ``pragma experimental ABIEncoderV2;`` - we kept
the same pragma, even though it is not considered experimental
anymore.
The set of types supported by the new encoder is a strict superset of
the ones supported by the old one. Contracts that use it can interact with ones
that do not without limitations. The reverse is possible only as long as the
non-``ABIEncoderV2`` contract does not try to make calls that would require
decoding types only supported by the new encoder. The compiler can detect this
and will issue an error. Simply enabling ``ABIEncoderV2`` for your contract is
enough to make the error go away.
.. note::
This pragma applies to all the code defined in the file where it is activated,
regardless of where that code ends up eventually. This means that a contract
without the ``ABIEncoderV2`` pragma can still contain code that uses the new encoder
by inheriting it from another contract. This is allowed if the new types are only
used internally and not in external function signatures.
Because the ABI coder v2 is not considered experimental anymore,
it can be selected via ``pragma abicoder v2`` (please see above)
since Solidity 0.7.4.
.. _smt_checker:

View File

@ -290,7 +290,7 @@ Array Members
.. note::
To use arrays of arrays in external (instead of public) functions, you need to
activate ABIEncoderV2.
activate ABI coder v2.
.. note::
In EVM versions before Byzantium, it was not possible to access

View File

@ -231,7 +231,7 @@ Input Description
"cse": false,
// Optimize representation of literal numbers and strings in code.
"constantOptimizer": false,
// The new Yul optimizer. Mostly operates on the code of ABIEncoderV2
// The new Yul optimizer. Mostly operates on the code of ABI coder v2
// and inline assembly.
// It is activated together with the global optimizer setting
// and can be deactivated here.

View File

@ -450,7 +450,7 @@ void ContractLevelChecker::checkLibraryRequirements(ContractDefinition const& _c
void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _contract)
{
if (_contract.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2))
if (*_contract.sourceUnit().annotation().useABICoderV2)
return;
if (_contract.isLibrary())
@ -469,7 +469,7 @@ void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _
{
solAssert(func.second->hasDeclaration(), "Function has no declaration?!");
if (!func.second->declaration().sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2))
if (!*func.second->declaration().sourceUnit().annotation().useABICoderV2)
continue;
auto const& currentLoc = func.second->declaration().location();
@ -489,9 +489,9 @@ void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _
errors,
std::string("Contract \"") +
_contract.name() +
"\" does not use ABIEncoderV2 but wants to inherit from a contract " +
"\" does not use ABI coder v2 but wants to inherit from a contract " +
"which uses types that require it. " +
"Use \"pragma experimental ABIEncoderV2;\" for the inheriting contract as well to enable the feature."
"Use \"pragma abicoder v2;\" for the inheriting contract as well to enable the feature."
);
}

View File

@ -73,6 +73,8 @@ void SyntaxChecker::endVisit(SourceUnit const& _sourceUnit)
// when reporting the warning, print the source name only
m_errorReporter.warning(3420_error, {-1, -1, _sourceUnit.location().source}, errorString);
}
if (!m_sourceUnit->annotation().useABICoderV2.set())
m_sourceUnit->annotation().useABICoderV2 = false;
m_sourceUnit = nullptr;
}
@ -113,9 +115,45 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
m_sourceUnit->annotation().experimentalFeatures.insert(feature);
if (!ExperimentalFeatureWithoutWarning.count(feature))
m_errorReporter.warning(2264_error, _pragma.location(), "Experimental features are turned on. Do not use experimental features on live deployments.");
if (feature == ExperimentalFeature::ABIEncoderV2)
{
if (m_sourceUnit->annotation().useABICoderV2.set())
{
if (!*m_sourceUnit->annotation().useABICoderV2)
m_errorReporter.syntaxError(
8273_error,
_pragma.location(),
"ABI coder v1 has already been selected through \"pragma abicoder v1\"."
);
}
else
m_sourceUnit->annotation().useABICoderV2 = true;
}
}
}
}
else if (_pragma.literals()[0] == "abicoder")
{
solAssert(m_sourceUnit, "");
if (
_pragma.literals().size() != 2 ||
!set<string>{"v1", "v2"}.count(_pragma.literals()[1])
)
m_errorReporter.syntaxError(
2745_error,
_pragma.location(),
"Expected either \"pragma abicoder v1\" or \"pragma abicoder v2\"."
);
else if (m_sourceUnit->annotation().useABICoderV2.set())
m_errorReporter.syntaxError(
3845_error,
_pragma.location(),
"ABI coder has already been selected for this source unit."
);
else
m_sourceUnit->annotation().useABICoderV2 = (_pragma.literals()[1] == "v2");
}
else if (_pragma.literals()[0] == "solidity")
{
vector<Token> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end());
@ -135,6 +173,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
}
else
m_errorReporter.syntaxError(4936_error, _pragma.location(), "Unknown pragma \"" + _pragma.literals()[0] + "\"");
return true;
}

View File

@ -39,6 +39,7 @@ namespace solidity::frontend
* - issues deprecation warnings for unary '+'
* - issues deprecation warning for throw
* - whether the msize instruction is used and the Yul optimizer is enabled at the same time.
* - selection of the ABI coder through pragmas.
*/
class SyntaxChecker: private ASTConstVisitor
{

View File

@ -395,13 +395,13 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
m_errorReporter.typeError(4103_error, _var.location(), message);
}
else if (
!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) &&
!useABICoderV2() &&
!typeSupportedByOldABIEncoder(*type(_var), _function.libraryFunction())
)
{
string message =
"This type is only supported in ABIEncoderV2. "
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature.";
"This type is only supported in ABI coder v2. "
"Use \"pragma abicoder v2;\" to enable the feature.";
if (_function.isConstructor())
message +=
" Alternatively, make the contract abstract and supply the "
@ -567,7 +567,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
else if (_variable.visibility() >= Visibility::Public)
{
FunctionType getter(_variable);
if (!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
if (!useABICoderV2())
{
vector<string> unsupportedTypes;
for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes())
@ -577,9 +577,9 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
m_errorReporter.typeError(
2763_error,
_variable.location(),
"The following types are only supported for getters in ABIEncoderV2: " +
"The following types are only supported for getters in ABI coder v2: " +
joinHumanReadable(unsupportedTypes) +
". Either remove \"public\" or use \"pragma experimental ABIEncoderV2;\" to enable the feature."
". Either remove \"public\" or use \"pragma abicoder v2;\" to enable the feature."
);
}
if (!getter.interfaceFunctionType())
@ -692,14 +692,14 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
if (!type(*var)->interfaceType(false))
m_errorReporter.typeError(3417_error, var->location(), "Internal or recursive type is not allowed as event parameter type.");
if (
!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) &&
!useABICoderV2() &&
!typeSupportedByOldABIEncoder(*type(*var), false /* isLibrary */)
)
m_errorReporter.typeError(
3061_error,
var->location(),
"This type is only supported in ABIEncoderV2. "
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
"This type is only supported in ABI coder v2. "
"Use \"pragma abicoder v2;\" to enable the feature."
);
}
if (_eventDef.isAnonymous() && numIndexed > 4)
@ -1897,7 +1897,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
bool const isPacked = _functionType->kind() == FunctionType::Kind::ABIEncodePacked;
solAssert(_functionType->padArguments() != isPacked, "ABI function with unexpected padding");
bool const abiEncoderV2 = experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2);
bool const abiEncoderV2 = useABICoderV2();
// Check for named arguments
if (!_functionCall.names().empty())
@ -2189,7 +2189,7 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
_functionType->kind() == FunctionType::Kind::Creation ||
_functionType->kind() == FunctionType::Kind::Event;
if (callRequiresABIEncoding && !experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
if (callRequiresABIEncoding && !useABICoderV2())
{
solAssert(!isVariadic, "");
solAssert(parameterTypes.size() == arguments.size(), "");
@ -2205,8 +2205,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
2443_error,
paramArgMap[i]->location(),
"The type of this parameter, " + parameterTypes[i]->toString(true) + ", "
"is only supported in ABIEncoderV2. "
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
"is only supported in ABI coder v2. "
"Use \"pragma abicoder v2;\" to enable the feature."
);
}
@ -2219,8 +2219,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
2428_error,
_functionCall.location(),
"The type of return parameter " + toString(i + 1) + ", " + returnParameterTypes[i]->toString(true) + ", "
"is only supported in ABIEncoderV2. "
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
"is only supported in ABI coder v2. "
"Use \"pragma abicoder v2;\" to enable the feature."
);
}
}
@ -2337,7 +2337,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
{
returnTypes = typeCheckABIDecodeAndRetrieveReturnType(
_functionCall,
experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)
useABICoderV2()
);
break;
}
@ -3384,10 +3384,11 @@ void TypeChecker::requireLValue(Expression const& _expression, bool _ordinaryAss
m_errorReporter.typeError(errorId, _expression.location(), description);
}
bool TypeChecker::experimentalFeatureActive(ExperimentalFeature _feature) const
bool TypeChecker::useABICoderV2() const
{
solAssert(m_currentSourceUnit, "");
if (m_currentContract)
solAssert(m_currentSourceUnit == &m_currentContract->sourceUnit(), "");
return m_currentSourceUnit->annotation().experimentalFeatures.count(_feature);
return *m_currentSourceUnit->annotation().useABICoderV2;
}

View File

@ -166,7 +166,7 @@ private:
/// Runs type checks on @a _expression to infer its type and then checks that it is an LValue.
void requireLValue(Expression const& _expression, bool _ordinaryAssignment);
bool experimentalFeatureActive(ExperimentalFeature _feature) const;
bool useABICoderV2() const;
/// @returns the current scope that can have function or type definitions.
/// This is either a contract or a source unit.

View File

@ -94,6 +94,7 @@ struct SourceUnitAnnotation: ASTAnnotation
SetOnce<std::map<ASTString, std::vector<Declaration const*>>> exportedSymbols;
/// Experimental features.
std::set<ExperimentalFeature> experimentalFeatures;
SetOnce<bool> useABICoderV2;
};
struct ScopableAnnotation

View File

@ -1162,7 +1162,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d
if (
!_arrayType.isByteArray() &&
_arrayType.baseType()->storageBytes() < 32 &&
m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)
m_context.useABICoderV2()
)
{
m_context << u256(32);

View File

@ -76,11 +76,8 @@ public:
langutil::EVMVersion const& evmVersion() const { return m_evmVersion; }
/// Update currently enabled set of experimental features.
void setExperimentalFeatures(std::set<ExperimentalFeature> const& _features) { m_experimentalFeatures = _features; }
std::set<ExperimentalFeature> const& experimentalFeaturesActive() const { return m_experimentalFeatures; }
/// @returns true if the given feature is enabled.
bool experimentalFeatureActive(ExperimentalFeature _feature) const { return m_experimentalFeatures.count(_feature); }
void setUseABICoderV2(bool _value) { m_useABICoderV2 = _value; }
bool useABICoderV2() const { return m_useABICoderV2; }
void addStateVariable(VariableDeclaration const& _declaration, u256 const& _storageOffset, unsigned _byteOffset);
void addImmutable(VariableDeclaration const& _declaration);
@ -361,8 +358,7 @@ private:
/// Version of the EVM to compile against.
langutil::EVMVersion m_evmVersion;
RevertStrings const m_revertStrings;
/// Activated experimental features.
std::set<ExperimentalFeature> m_experimentalFeatures;
bool m_useABICoderV2 = false;
/// Other already compiled contracts to be used in contract creation calls.
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> m_otherCompilers;
/// Storage offsets of state variables

View File

@ -230,7 +230,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMemory)
{
/// Stack: <source_offset> <length>
if (m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
if (m_context.useABICoderV2())
{
// Use the new Yul-based decoding function
auto stackHeightBefore = m_context.stackHeight();
@ -412,7 +412,7 @@ void CompilerUtils::encodeToMemory(
)
{
// stack: <v1> <v2> ... <vn> <mem>
bool const encoderV2 = m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2);
bool const encoderV2 = m_context.useABICoderV2();
TypePointers targetTypes = _targetTypes.empty() ? _givenTypes : _targetTypes;
solAssert(targetTypes.size() == _givenTypes.size(), "");
for (TypePointer& t: targetTypes)

View File

@ -126,7 +126,7 @@ void ContractCompiler::initializeContext(
map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers
)
{
m_context.setExperimentalFeatures(_contract.sourceUnit().annotation().experimentalFeatures);
m_context.setUseABICoderV2(*_contract.sourceUnit().annotation().useABICoderV2);
m_context.setOtherCompilers(_otherCompilers);
m_context.setMostDerivedContract(_contract);
if (m_runtimeCompiler)
@ -1324,13 +1324,13 @@ void ContractCompiler::appendModifierOrFunctionCode()
if (codeBlock)
{
std::set<ExperimentalFeature> experimentalFeaturesOutside = m_context.experimentalFeaturesActive();
m_context.setExperimentalFeatures(codeBlock->sourceUnit().annotation().experimentalFeatures);
bool coderV2Outside = m_context.useABICoderV2();
m_context.setUseABICoderV2(*codeBlock->sourceUnit().annotation().useABICoderV2);
m_returnTags.emplace_back(m_context.newTag(), m_context.stackHeight());
codeBlock->accept(*this);
m_context.setExperimentalFeatures(experimentalFeaturesOutside);
m_context.setUseABICoderV2(coderV2Outside);
solAssert(!m_returnTags.empty(), "");
m_context << m_returnTags.back().first;

View File

@ -1682,7 +1682,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
{
solAssert(memberType->calldataEncodedSize() > 0, "");
solAssert(memberType->storageBytes() <= 32, "");
if (memberType->storageBytes() < 32 && m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
if (memberType->storageBytes() < 32 && m_context.useABICoderV2())
{
m_context << u256(32);
CompilerUtils(m_context).abiDecodeV2({memberType}, false);
@ -2490,7 +2490,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
// memory pointer), but kept references to the return data for
// (statically-sized) arrays
bool needToUpdateFreeMemoryPtr = false;
if (dynamicReturnSize || m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
if (dynamicReturnSize || m_context.useABICoderV2())
needToUpdateFreeMemoryPtr = true;
else
for (auto const& retType: returnTypes)

View File

@ -34,6 +34,7 @@
#include <libsolidity/codegen/Compiler.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/TypeChecker.h>
#include <libsolidity/analysis/SyntaxChecker.h>
#include <liblangutil/ErrorReporter.h>
#include <boost/test/unit_test.hpp>
@ -61,6 +62,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode)
BOOST_CHECK(!!sourceUnit);
Scoper::assignScopes(*sourceUnit);
BOOST_REQUIRE(SyntaxChecker(errorReporter, false).checkSyntax(*sourceUnit));
GlobalContext globalContext;
NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter);
DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion());

View File

@ -27,6 +27,7 @@
#include <libsolidity/parsing/Parser.h>
#include <libsolidity/analysis/NameAndTypeResolver.h>
#include <libsolidity/analysis/Scoper.h>
#include <libsolidity/analysis/SyntaxChecker.h>
#include <libsolidity/analysis/DeclarationTypeChecker.h>
#include <libsolidity/codegen/CompilerContext.h>
#include <libsolidity/codegen/ExpressionCompiler.h>
@ -93,18 +94,20 @@ Declaration const& resolveDeclaration(
}
bytes compileFirstExpression(
const string& _sourceCode,
string const& _sourceCode,
vector<vector<string>> _functions = {},
vector<vector<string>> _localVariables = {}
)
{
string sourceCode = "pragma solidity >=0.0; // SPDX-License-Identifier: GPL-3\n" + _sourceCode;
ASTPointer<SourceUnit> sourceUnit;
try
{
ErrorList errors;
ErrorReporter errorReporter(errors);
sourceUnit = Parser(errorReporter, solidity::test::CommonOptions::get().evmVersion()).parse(
make_shared<Scanner>(CharStream(_sourceCode, ""))
make_shared<Scanner>(CharStream(sourceCode, ""))
);
if (!sourceUnit)
return bytes();
@ -119,6 +122,7 @@ bytes compileFirstExpression(
ErrorReporter errorReporter(errors);
GlobalContext globalContext;
Scoper::assignScopes(*sourceUnit);
BOOST_REQUIRE(SyntaxChecker(errorReporter, false).checkSyntax(*sourceUnit));
NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter);
resolver.registerDeclarations(*sourceUnit);
BOOST_REQUIRE_MESSAGE(resolver.resolveNamesAndTypes(*sourceUnit), "Resolving names failed");
@ -186,7 +190,7 @@ BOOST_AUTO_TEST_CASE(literal_false)
{
char const* sourceCode = R"(
contract test {
function f() { bool x = false; }
function f() public { bool x = false; }
}
)";
bytes code = compileFirstExpression(sourceCode);
@ -199,7 +203,7 @@ BOOST_AUTO_TEST_CASE(int_literal)
{
char const* sourceCode = R"(
contract test {
function f() { uint x = 0x12345678901234567890; }
function f() public { uint x = 0x12345678901234567890; }
}
)";
bytes code = compileFirstExpression(sourceCode);
@ -228,7 +232,7 @@ BOOST_AUTO_TEST_CASE(int_with_gwei_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
function test () {
function f() public {
uint x = 1 gwei;
}
}
@ -258,7 +262,7 @@ BOOST_AUTO_TEST_CASE(comparison)
{
char const* sourceCode = R"(
contract test {
function f() { bool x = (0x10aa < 0x11aa) != true; }
function f() public { bool x = (0x10aa < 0x11aa) != true; }
}
)";
bytes code = compileFirstExpression(sourceCode);
@ -290,7 +294,7 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
{
char const* sourceCode = R"(
contract test {
function f() { bool x = true != (4 <= 8 + 10 || 9 != 2); }
function f() public { bool x = true != (4 <= 8 + 10 || 9 != 2); }
}
)";
bytes code = compileFirstExpression(sourceCode);
@ -321,7 +325,7 @@ BOOST_AUTO_TEST_CASE(arithmetic)
{
char const* sourceCode = R"(
contract test {
function f(uint y) { ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }
function f(uint y) public { ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }
}
)";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
@ -402,7 +406,7 @@ BOOST_AUTO_TEST_CASE(unary_operators)
{
char const* sourceCode = R"(
contract test {
function f(int y) { !(~- y == 2); }
function f(int y) public { !(~- y == 2); }
}
)";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
@ -492,7 +496,7 @@ BOOST_AUTO_TEST_CASE(assignment)
{
char const* sourceCode = R"(
contract test {
function f(uint a, uint b) { (a += b) * 2; }
function f(uint a, uint b) public { (a += b) * 2; }
}
)";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}});
@ -530,7 +534,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_8bits)
{
char const* sourceCode = R"(
contract test {
function f() { int8 x = -0x80; }
function f() public { int8 x = -0x80; }
}
)";
bytes code = compileFirstExpression(sourceCode);
@ -543,7 +547,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_16bits)
{
char const* sourceCode = R"(
contract test {
function f() { int64 x = ~0xabc; }
function f() public { int64 x = ~0xabc; }
}
)";
bytes code = compileFirstExpression(sourceCode);
@ -558,7 +562,7 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals)
// have been applied
char const* sourceCode = R"(
contract test {
function f() { uint8 x = (0x00ffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; }
function f() public { uint8 x = (0x00ffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; }
}
)";
bytes code = compileFirstExpression(sourceCode);
@ -571,7 +575,7 @@ BOOST_AUTO_TEST_CASE(blockhash)
{
char const* sourceCode = R"(
contract test {
function f() {
function f() public {
blockhash(3);
}
}
@ -603,7 +607,7 @@ BOOST_AUTO_TEST_CASE(selfbalance)
{
char const* sourceCode = R"(
contract test {
function f() returns (uint) {
function f() public returns (uint) {
return address(this).balance;
}
}

View File

@ -0,0 +1,4 @@
pragma experimental ABIEncoderV2;
pragma abicoder v1;
// ----
// SyntaxError 3845: (34-53): ABI coder has already been selected for this source unit.

View File

@ -0,0 +1,4 @@
pragma abicoder v1;
pragma experimental ABIEncoderV2;
// ----
// SyntaxError 8273: (20-53): ABI coder v1 has already been selected through "pragma abicoder v1".

View File

@ -0,0 +1,3 @@
pragma abicoder something;
// ----
// SyntaxError 2745: (0-26): Expected either "pragma abicoder v1" or "pragma abicoder v2".

View File

@ -0,0 +1,4 @@
pragma experimental ABIEncoderV2;
pragma abicoder v2;
// ----
// SyntaxError 3845: (34-53): ABI coder has already been selected for this source unit.

View File

@ -0,0 +1 @@
pragma abicoder v1;

View File

@ -0,0 +1,4 @@
pragma abicoder v1;
pragma abicoder v1;
// ----
// SyntaxError 3845: (20-39): ABI coder has already been selected for this source unit.

View File

@ -0,0 +1,2 @@
pragma abicoder v2;
pragma experimental ABIEncoderV2;

View File

@ -17,4 +17,4 @@ contract Test {
}
}
// ----
// TypeError 2443: (B:71-80): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2443: (B:71-80): The type of this parameter, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -17,4 +17,4 @@ contract Test {
}
}
// ----
// TypeError 2443: (B:90-100): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2443: (B:90-100): The type of this parameter, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -19,4 +19,4 @@ contract Test {
}
}
// ----
// TypeError 2443: (B:146-155): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2443: (B:146-155): The type of this parameter, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -13,4 +13,4 @@ contract D {
}
}
// ----
// TypeError 2428: (B:65-76): The type of return parameter 1, string[], is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2428: (B:65-76): The type of return parameter 1, string[], is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -17,4 +17,4 @@ contract Test {
}
}
// ----
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -17,4 +17,4 @@ contract Test {
}
}
// ----
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -16,4 +16,4 @@ contract Test {
}
}
// ----
// TypeError 2443: (B:74-84): The type of this parameter, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2443: (B:74-84): The type of this parameter, struct L.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -19,4 +19,4 @@ contract D {
}
}
// ----
// TypeError 2428: (B:86-97): The type of return parameter 1, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2428: (B:86-97): The type of return parameter 1, struct L.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -17,4 +17,4 @@ contract Test {
}
}
// ----
// TypeError 2428: (B:70-77): The type of return parameter 1, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2428: (B:70-77): The type of return parameter 1, struct L.Item, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -13,4 +13,4 @@ import "A";
contract D is C {}
// ----
// TypeError 6594: (B:13-31): Contract "D" does not use ABIEncoderV2 but wants to inherit from a contract which uses types that require it. Use "pragma experimental ABIEncoderV2;" for the inheriting contract as well to enable the feature.
// TypeError 6594: (B:13-31): Contract "D" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature.

View File

@ -13,4 +13,4 @@ import "A";
contract D is C {}
// ----
// TypeError 6594: (B:13-31): Contract "D" does not use ABIEncoderV2 but wants to inherit from a contract which uses types that require it. Use "pragma experimental ABIEncoderV2;" for the inheriting contract as well to enable the feature.
// TypeError 6594: (B:13-31): Contract "D" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature.

View File

@ -27,4 +27,4 @@ contract C is B {
{}
}
// ----
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -29,4 +29,4 @@ contract C is B {
{}
}
// ----
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -3,5 +3,5 @@ contract Test {
function g(uint[][1] calldata) external { }
}
// ----
// TypeError 4957: (31-48): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 4957: (78-96): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 4957: (31-48): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.
// TypeError 4957: (78-96): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -2,4 +2,4 @@ contract C {
constructor(uint[][][] memory t) {}
}
// ----
// TypeError 4957: (26-45): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. Alternatively, make the contract abstract and supply the constructor arguments from a derived contract.
// TypeError 4957: (26-45): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. Alternatively, make the contract abstract and supply the constructor arguments from a derived contract.

View File

@ -2,4 +2,4 @@ contract c {
event E(uint[][]);
}
// ----
// TypeError 3061: (25-33): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 3061: (25-33): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -3,4 +3,4 @@ contract c {
event E(S);
}
// ----
// TypeError 3061: (61-62): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 3061: (61-62): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -3,4 +3,4 @@ contract c {
event E(S);
}
// ----
// TypeError 3061: (51-52): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 3061: (51-52): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -3,4 +3,4 @@ contract c {
event E(S indexed);
}
// ----
// TypeError 3061: (51-60): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 3061: (51-60): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -8,4 +8,4 @@ contract C {
mapping(uint256 => X) public m;
}
// ----
// TypeError 2763: (88-118): The following types are only supported for getters in ABIEncoderV2: struct C.Y memory. Either remove "public" or use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 2763: (88-118): The following types are only supported for getters in ABI coder v2: struct C.Y memory. Either remove "public" or use "pragma abicoder v2;" to enable the feature.

View File

@ -16,4 +16,4 @@ contract B is A { }
import "./B.sol";
contract C is B { }
// ----
// TypeError 6594: (C.sol:18-37): Contract "C" does not use ABIEncoderV2 but wants to inherit from a contract which uses types that require it. Use "pragma experimental ABIEncoderV2;" for the inheriting contract as well to enable the feature.
// TypeError 6594: (C.sol:18-37): Contract "C" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature.

View File

@ -14,4 +14,4 @@ contract B is A { }
import "./B.sol";
contract C is B { }
// ----
// TypeError 6594: (B.sol:18-37): Contract "B" does not use ABIEncoderV2 but wants to inherit from a contract which uses types that require it. Use "pragma experimental ABIEncoderV2;" for the inheriting contract as well to enable the feature.
// TypeError 6594: (B.sol:18-37): Contract "B" does not use ABI coder v2 but wants to inherit from a contract which uses types that require it. Use "pragma abicoder v2;" for the inheriting contract as well to enable the feature.

View File

@ -2,4 +2,4 @@ contract C {
function f() public pure returns (string[][] memory) {}
}
// ----
// TypeError 4957: (51-68): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 4957: (51-68): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -2,4 +2,4 @@ contract C {
function f() public pure returns (uint[][2] memory) {}
}
// ----
// TypeError 4957: (51-67): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 4957: (51-67): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.

View File

@ -3,4 +3,4 @@ contract C {
function f() public pure returns (S memory x) {}
}
// ----
// TypeError 4957: (80-90): This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
// TypeError 4957: (80-90): This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature.