mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10013 from ethereum/errorCodesPanic
Panic with error codes.
This commit is contained in:
commit
f22cb64710
@ -7,6 +7,7 @@ Breaking Changes:
|
||||
* Type System: Unary negation can only be used on signed integers, not on unsigned integers.
|
||||
* Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type.
|
||||
* Parser: Exponentiation is right associative. ``a**b**c`` is parsed as ``a**(b**c)``.
|
||||
* Code Generator: Use ``revert`` with error signature ``Panic(uint256)`` and error codes instead of invalid opcode on failing assertions.
|
||||
|
||||
|
||||
Language Features:
|
||||
|
@ -18,6 +18,15 @@ and it does something else afterwards.
|
||||
* Exponentiation is right associative, i.e., the expression ``a**b**c`` is parsed as ``a**(b**c)``.
|
||||
Before 0.8.0, it was parsed as ``(a**b)**c``.
|
||||
|
||||
Semantic only Changes
|
||||
=====================
|
||||
|
||||
* Failing assertions (and other internal checks like division by zero) do not use the invalid opcode anymore but instead revert
|
||||
with error data equal to a function call to ``Panic(uint256)`` with an error code specific to the circumstances.
|
||||
|
||||
This will save gas on errors while it still allows static analysis tools to detect these situations.
|
||||
|
||||
|
||||
Syntactic Only Changes
|
||||
======================
|
||||
|
||||
|
@ -564,35 +564,53 @@ of an exception instead of "bubbling up".
|
||||
|
||||
Exceptions can be caught with the ``try``/``catch`` statement.
|
||||
|
||||
``assert`` and ``require``
|
||||
--------------------------
|
||||
Exceptions can contain data that is passed back to the caller.
|
||||
This data consists of a 4-byte selector and subsequent :ref:`ABI-encoded<abi>` data.
|
||||
The selector is computed in the same way as a function selector, i.e.,
|
||||
the first four bytes of the keccak256-hash of a function
|
||||
signature - in this case an error signature.
|
||||
|
||||
Currently, Solidity supports two error signatures: ``Error(string)``
|
||||
and ``Panic(uint256)``. The first ("error") is used for "regular" error conditions
|
||||
while the second ("panic") is used for errors that should not be present in bug-free code.
|
||||
|
||||
Panic via ``assert`` and Error via ``require``
|
||||
----------------------------------------------
|
||||
|
||||
The convenience functions ``assert`` and ``require`` can be used to check for conditions and throw an exception
|
||||
if the condition is not met.
|
||||
|
||||
The ``assert`` function should only be used to test for internal
|
||||
The ``assert`` function creates an error of type ``Panic(uint256)``.
|
||||
The same error is created by the compiler in certain situations as listed below.
|
||||
|
||||
Assert should only be used to test for internal
|
||||
errors, and to check invariants. Properly functioning code should
|
||||
never reach a failing ``assert`` statement; if this happens there
|
||||
never create a Panic, not even on invalid external input.
|
||||
If this happens, then there
|
||||
is a bug in your contract which you should fix. Language analysis
|
||||
tools can evaluate your contract to identify the conditions and
|
||||
function calls which will reach a failing ``assert``.
|
||||
function calls which will cause a Panic.
|
||||
|
||||
An ``assert``-style exception is generated in the following situations:
|
||||
A Panic exception is generated in the following situations.
|
||||
The error code supplied with the error data indicates the kind of panic.
|
||||
|
||||
#. If you access an array or an array slice at a too large or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``).
|
||||
#. If you access a fixed-length ``bytesN`` at a too large or negative index.
|
||||
#. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
|
||||
#. If an arithmetic operation results in under- or overflow outside of an ``unchecked { ... }`` block.
|
||||
#. If you convert a value too big or negative into an enum type.
|
||||
#. If you call a zero-initialized variable of internal function type.
|
||||
#. If you call ``assert`` with an argument that evaluates to false.
|
||||
#. 0x01: If you call ``assert`` with an argument that evaluates to false.
|
||||
#. 0x11: If an arithmetic operation results in underflow or overflow outside of an ``unchecked { ... }`` block.
|
||||
#. 0x12; If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
|
||||
#. 0x21: If you convert a value that is too big or negative into an enum type.
|
||||
#. 0x31: If you call ``.pop()`` on an empty array.
|
||||
#. 0x32: If you access an array, ``bytesN`` or an array slice at an out-of-bounds or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``).
|
||||
#. 0x41: If you allocate too much memory or create an array that is too large.
|
||||
#. 0x51: If you call a zero-initialized variable of internal function type.
|
||||
|
||||
The ``require`` function should be used to ensure valid conditions
|
||||
The ``require`` function either creates an error of type ``Error(string)``
|
||||
or an error without any error data and it
|
||||
should be used to ensure valid conditions
|
||||
that cannot be detected until execution time.
|
||||
This includes conditions on inputs
|
||||
or return values from calls to external contracts.
|
||||
|
||||
A ``require``-style exception is generated in the following situations:
|
||||
A ``Error(string)`` exception is generated in the following situations:
|
||||
|
||||
#. Calling ``require`` with an argument that evaluates to ``false``.
|
||||
#. If you call a function via a message call but it does not finish
|
||||
@ -611,6 +629,11 @@ A ``require``-style exception is generated in the following situations:
|
||||
|
||||
You can optionally provide a message string for ``require``, but not for ``assert``.
|
||||
|
||||
.. note::
|
||||
If you do not provide a string argument to ``require``, it will revert
|
||||
with empty error data, not even including the error selector.
|
||||
|
||||
|
||||
The following example shows how you can use ``require`` to check conditions on inputs
|
||||
and ``assert`` for internal error checking.
|
||||
|
||||
@ -633,29 +656,29 @@ and ``assert`` for internal error checking.
|
||||
}
|
||||
|
||||
Internally, Solidity performs a revert operation (instruction
|
||||
``0xfd``) for a ``require``-style exception and executes an invalid operation
|
||||
(instruction ``0xfe``) to throw an ``assert``-style exception. In both cases, this causes
|
||||
``0xfd``). This causes
|
||||
the EVM to revert all changes made to the state. The reason for reverting
|
||||
is that there is no safe way to continue execution, because an expected effect
|
||||
did not occur. Because we want to keep the atomicity of transactions, the
|
||||
safest action is to revert all changes and make the whole transaction
|
||||
(or at least call) without effect.
|
||||
|
||||
In both cases, the caller can react on such failures using ``try``/``catch``
|
||||
(in the failing ``assert``-style exception only if enough gas is left), but
|
||||
In both cases, the caller can react on such failures using ``try``/``catch``, but
|
||||
the changes in the caller will always be reverted.
|
||||
|
||||
.. note::
|
||||
|
||||
``assert``-style exceptions consume all gas available to the call,
|
||||
while ``require``-style exceptions do not consume any gas starting from the Metropolis release.
|
||||
Panic exceptions used to use the ``invalid`` opcode before Solidity 0.8.0,
|
||||
which consumed all gas available to the call.
|
||||
Exceptions that use ``require`` used to consume all gas until before the Metropolis release.
|
||||
|
||||
``revert``
|
||||
----------
|
||||
|
||||
The ``revert`` function is another way to trigger exceptions from within other code blocks to flag an error and
|
||||
revert the current call. The function takes an optional string
|
||||
message containing details about the error that is passed back to the caller.
|
||||
message containing details about the error that is passed back to the caller
|
||||
and it will create an ``Error(string)`` exception.
|
||||
|
||||
The following example shows how to use an error string together with ``revert`` and the equivalent ``require``:
|
||||
|
||||
@ -726,9 +749,7 @@ A failure in an external call can be caught using a try/catch statement, as foll
|
||||
errorCount++;
|
||||
return (0, false);
|
||||
} catch (bytes memory /*lowLevelData*/) {
|
||||
// This is executed in case revert() was used
|
||||
// or there was a failing assertion, division
|
||||
// by zero, etc. inside getData.
|
||||
// This is executed in case revert() was used.
|
||||
errorCount++;
|
||||
return (0, false);
|
||||
}
|
||||
@ -754,9 +775,8 @@ It is planned to support other types of error data in the future.
|
||||
The string ``Error`` is currently parsed as is and is not treated as an identifier.
|
||||
|
||||
The clause ``catch (bytes memory lowLevelData)`` is executed if the error signature
|
||||
does not match any other clause, there was an error during decoding of the error
|
||||
message, if there was a failing assertion in the external
|
||||
call (for example due to a division by zero or a failing ``assert()``) or
|
||||
does not match any other clause, if there was an error while decoding the error
|
||||
message, or
|
||||
if no error data was provided with the exception.
|
||||
The declared variable provides access to the low-level error data in that case.
|
||||
|
||||
|
@ -107,7 +107,7 @@ Note that in contrast, division on :ref:`literals<rational_literals>` results in
|
||||
of arbitrary precision.
|
||||
|
||||
.. note::
|
||||
Division by zero causes a failing assert. This check can **not** be disabled through ``unchecked { ... }``.
|
||||
Division by zero causes a :ref:`Panic error<assert-and-require>`. This check can **not** be disabled through ``unchecked { ... }``.
|
||||
|
||||
.. note::
|
||||
The expression ``type(int).min / (-1)`` is the only case where division causes an overflow.
|
||||
@ -127,7 +127,7 @@ results in the same sign as its left operand (or zero) and ``a % n == -(-a % n)`
|
||||
* ``int256(-5) % int256(-2) == int256(-1)``
|
||||
|
||||
.. note::
|
||||
Modulo with zero causes a failing assert. This check can **not** be disabled through ``unchecked { ... }``.
|
||||
Modulo with zero causes a :ref:`Panic error<assert-and-require>`. This check can **not** be disabled through ``unchecked { ... }``.
|
||||
|
||||
Exponentiation
|
||||
^^^^^^^^^^^^^^
|
||||
@ -562,7 +562,8 @@ Enums
|
||||
|
||||
Enums are one way to create a user-defined type in Solidity. They are explicitly convertible
|
||||
to and from all integer types but implicit conversion is not allowed. The explicit conversion
|
||||
from integer checks at runtime that the value lies inside the range of the enum and causes a failing assert otherwise.
|
||||
from integer checks at runtime that the value lies inside the range of the enum and causes a
|
||||
:ref:`Panic error<assert-and-require>` otherwise.
|
||||
Enums require at least one member, and its default value when declared is the first member.
|
||||
|
||||
The data representation is the same as for enums in C: The options are represented by
|
||||
@ -656,7 +657,7 @@ On the other hand, a ``non-payable`` function will reject Ether sent to it,
|
||||
so ``non-payable`` functions cannot be converted to ``payable`` functions.
|
||||
|
||||
If a function type variable is not initialised, calling it results
|
||||
in a failed assertion. The same happens if you call a function after using ``delete``
|
||||
in a :ref:`Panic error<assert-and-require>`. The same happens if you call a function after using ``delete``
|
||||
on it.
|
||||
|
||||
If external function types are used outside of the context of Solidity,
|
||||
|
@ -144,7 +144,7 @@ See the dedicated section on :ref:`assert and require<assert-and-require>` for
|
||||
more details on error handling and when to use which function.
|
||||
|
||||
``assert(bool condition)``
|
||||
causes an invalid opcode and thus state change reversion if the condition is not met - to be used for internal errors.
|
||||
causes a Panic error and thus state change reversion if the condition is not met - to be used for internal errors.
|
||||
|
||||
``require(bool condition)``
|
||||
reverts if the condition is not met - to be used for errors in inputs or external components.
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include <libsolidity/codegen/CompilerUtils.h>
|
||||
#include <libsolidity/codegen/LValue.h>
|
||||
|
||||
#include <libsolutil/FunctionSelector.h>
|
||||
#include <libsolutil/Whiskers.h>
|
||||
|
||||
#include <libevmasm/Instruction.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
@ -857,13 +860,17 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
|
||||
if (_type.isByteArray())
|
||||
{
|
||||
m_context.appendInlineAssembly(R"({
|
||||
util::Whiskers code(R"({
|
||||
let slot_value := sload(ref)
|
||||
switch and(slot_value, 1)
|
||||
case 0 {
|
||||
// short byte array
|
||||
let length := and(div(slot_value, 2), 0x1f)
|
||||
if iszero(length) { invalid() }
|
||||
if iszero(length) {
|
||||
mstore(0, <panicSelector>)
|
||||
mstore(4, <emptyArrayPop>)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
// Zero-out the suffix including the least significant byte.
|
||||
let mask := sub(exp(0x100, sub(33, length)), 1)
|
||||
@ -901,7 +908,10 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
sstore(ref, slot_value)
|
||||
}
|
||||
}
|
||||
})", {"ref"});
|
||||
})");
|
||||
code("panicSelector", util::selectorFromSignature("Panic(uint256)").str());
|
||||
code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop)));
|
||||
m_context.appendInlineAssembly(code.render(), {"ref"});
|
||||
m_context << Instruction::POP;
|
||||
}
|
||||
else
|
||||
@ -912,7 +922,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
m_context << Instruction::DUP1;
|
||||
// stack: ArrayReference oldLength oldLength
|
||||
m_context << Instruction::ISZERO;
|
||||
m_context.appendConditionalInvalid();
|
||||
m_context.appendConditionalPanic(util::PanicCode::EmptyArrayPop);
|
||||
|
||||
// Stack: ArrayReference oldLength
|
||||
m_context << u256(1) << Instruction::SWAP1 << Instruction::SUB;
|
||||
@ -1058,7 +1068,7 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
|
||||
// check out-of-bounds access
|
||||
m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO;
|
||||
// out-of-bounds access throws exception
|
||||
m_context.appendConditionalInvalid();
|
||||
m_context.appendConditionalPanic(util::PanicCode::ArrayOutOfBounds);
|
||||
}
|
||||
if (location == DataLocation::CallData && _arrayType.isDynamicallySized())
|
||||
// remove length if present
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
/// Stack pre: reference (excludes byte offset)
|
||||
/// Stack post: new_length
|
||||
void incrementDynamicArraySize(ArrayType const& _type) const;
|
||||
/// Decrements the size of a dynamic array by one if length is nonzero. Causes an invalid instruction otherwise.
|
||||
/// Decrements the size of a dynamic array by one if length is nonzero. Causes a Panic otherwise.
|
||||
/// Clears the removed data element. In case of a byte array, this might move the data.
|
||||
/// Stack pre: reference
|
||||
/// Stack post:
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <libyul/Utilities.h>
|
||||
|
||||
#include <libsolutil/Whiskers.h>
|
||||
#include <libsolutil/FunctionSelector.h>
|
||||
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <liblangutil/Scanner.h>
|
||||
@ -330,16 +331,24 @@ CompilerContext& CompilerContext::appendJump(evmasm::AssemblyItem::JumpType _jum
|
||||
return *this << item;
|
||||
}
|
||||
|
||||
CompilerContext& CompilerContext::appendInvalid()
|
||||
CompilerContext& CompilerContext::appendPanic(util::PanicCode _code)
|
||||
{
|
||||
return *this << Instruction::INVALID;
|
||||
Whiskers templ(R"({
|
||||
mstore(0, <selector>)
|
||||
mstore(4, <code>)
|
||||
revert(0, 0x24)
|
||||
})");
|
||||
templ("selector", util::selectorFromSignature("Panic(uint256)").str());
|
||||
templ("code", u256(_code).str());
|
||||
appendInlineAssembly(templ.render());
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompilerContext& CompilerContext::appendConditionalInvalid()
|
||||
CompilerContext& CompilerContext::appendConditionalPanic(util::PanicCode _code)
|
||||
{
|
||||
*this << Instruction::ISZERO;
|
||||
evmasm::AssemblyItem afterTag = appendConditionalJump();
|
||||
*this << Instruction::INVALID;
|
||||
appendPanic(_code);
|
||||
*this << afterTag;
|
||||
return *this;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
#include <libsolutil/Common.h>
|
||||
#include <libsolutil/ErrorCodes.h>
|
||||
|
||||
#include <libyul/AsmAnalysisInfo.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
@ -195,10 +196,10 @@ public:
|
||||
evmasm::AssemblyItem appendJumpToNew() { return m_asm->appendJump().tag(); }
|
||||
/// Appends a JUMP to a tag already on the stack
|
||||
CompilerContext& appendJump(evmasm::AssemblyItem::JumpType _jumpType = evmasm::AssemblyItem::JumpType::Ordinary);
|
||||
/// Appends an INVALID instruction
|
||||
CompilerContext& appendInvalid();
|
||||
/// Appends a conditional INVALID instruction
|
||||
CompilerContext& appendConditionalInvalid();
|
||||
/// Appends code to revert with a Panic(uint256) error.
|
||||
CompilerContext& appendPanic(util::PanicCode _code);
|
||||
/// Appends code to revert with a Panic(uint256) error if the topmost stack element is nonzero.
|
||||
CompilerContext& appendConditionalPanic(util::PanicCode _code);
|
||||
/// Appends a REVERT(0, 0) call
|
||||
/// @param _message is an optional revert message used in debug mode
|
||||
CompilerContext& appendRevert(std::string const& _message = "");
|
||||
|
@ -810,7 +810,7 @@ void CompilerUtils::convertType(
|
||||
if (_asPartOfArgumentDecoding)
|
||||
m_context.appendConditionalRevert(false, "Enum out of range");
|
||||
else
|
||||
m_context.appendConditionalInvalid();
|
||||
m_context.appendConditionalPanic(util::PanicCode::EnumConversionError);
|
||||
enumOverflowCheckPending = false;
|
||||
}
|
||||
break;
|
||||
@ -849,7 +849,7 @@ void CompilerUtils::convertType(
|
||||
EnumType const& enumType = dynamic_cast<decltype(enumType)>(_targetType);
|
||||
solAssert(enumType.numberOfMembers() > 0, "empty enum should have caused a parser error.");
|
||||
m_context << u256(enumType.numberOfMembers() - 1) << Instruction::DUP2 << Instruction::GT;
|
||||
m_context.appendConditionalInvalid();
|
||||
m_context.appendConditionalPanic(util::PanicCode::EnumConversionError);
|
||||
enumOverflowCheckPending = false;
|
||||
}
|
||||
else if (targetTypeCategory == Type::Category::FixedPoint)
|
||||
@ -1213,13 +1213,13 @@ void CompilerUtils::pushZeroValue(Type const& _type)
|
||||
if (funType->kind() == FunctionType::Kind::Internal)
|
||||
{
|
||||
m_context << m_context.lowLevelFunctionTag("$invalidFunction", 0, 0, [](CompilerContext& _context) {
|
||||
_context.appendInvalid();
|
||||
_context.appendPanic(util::PanicCode::InvalidInternalFunction);
|
||||
});
|
||||
if (CompilerContext* runCon = m_context.runtimeContext())
|
||||
{
|
||||
leftShiftNumberOnStack(32);
|
||||
m_context << runCon->lowLevelFunctionTag("$invalidFunction", 0, 0, [](CompilerContext& _context) {
|
||||
_context.appendInvalid();
|
||||
_context.appendPanic(util::PanicCode::InvalidInternalFunction);
|
||||
}).toSubAssemblyTag(m_context.runtimeSub());
|
||||
m_context << Instruction::OR;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
|
||||
#include <libsolutil/Whiskers.h>
|
||||
#include <libsolutil/FunctionSelector.h>
|
||||
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
@ -229,19 +230,26 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract)
|
||||
m_context.pushSubroutineSize(m_context.runtimeSub());
|
||||
m_context.pushSubroutineOffset(m_context.runtimeSub());
|
||||
// This code replaces the address added by appendDeployTimeAddress().
|
||||
m_context.appendInlineAssembly(R"(
|
||||
{
|
||||
// If code starts at 11, an mstore(0) writes to the full PUSH20 plus data
|
||||
// without the need for a shift.
|
||||
let codepos := 11
|
||||
codecopy(codepos, subOffset, subSize)
|
||||
// Check that the first opcode is a PUSH20
|
||||
if iszero(eq(0x73, byte(0, mload(codepos)))) { invalid() }
|
||||
mstore(0, address())
|
||||
mstore8(codepos, 0x73)
|
||||
return(codepos, subSize)
|
||||
}
|
||||
)", {"subSize", "subOffset"});
|
||||
m_context.appendInlineAssembly(
|
||||
Whiskers(R"(
|
||||
{
|
||||
// If code starts at 11, an mstore(0) writes to the full PUSH20 plus data
|
||||
// without the need for a shift.
|
||||
let codepos := 11
|
||||
codecopy(codepos, subOffset, subSize)
|
||||
// Check that the first opcode is a PUSH20
|
||||
if iszero(eq(0x73, byte(0, mload(codepos)))) {
|
||||
mstore(0, <panicSig>)
|
||||
mstore(4, 0)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
mstore(0, address())
|
||||
mstore8(codepos, 0x73)
|
||||
return(codepos, subSize)
|
||||
}
|
||||
)")("panicSig", util::selectorFromSignature("Panic(uint256)").str()).render(),
|
||||
{"subSize", "subOffset"}
|
||||
);
|
||||
|
||||
return m_context.runtimeSub();
|
||||
}
|
||||
|
@ -933,7 +933,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
acceptAndConvert(*arguments[2], *TypeProvider::uint256());
|
||||
m_context << Instruction::DUP1 << Instruction::ISZERO;
|
||||
m_context.appendConditionalInvalid();
|
||||
m_context.appendConditionalPanic(util::PanicCode::DivisionByZero);
|
||||
for (unsigned i = 1; i < 3; i ++)
|
||||
acceptAndConvert(*arguments[2 - i], *TypeProvider::uint256());
|
||||
if (function.kind() == FunctionType::Kind::AddMod)
|
||||
@ -1051,7 +1051,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
m_context << u256(0xffffffffffffffff);
|
||||
m_context << Instruction::DUP2;
|
||||
m_context << Instruction::GT;
|
||||
m_context.appendConditionalRevert();
|
||||
m_context.appendConditionalPanic(PanicCode::ResourceError);
|
||||
|
||||
// Stack: requested_length
|
||||
utils().fetchFreeMemoryPointer();
|
||||
@ -1121,7 +1121,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
auto success = m_context.appendConditionalJump();
|
||||
if (function.kind() == FunctionType::Kind::Assert)
|
||||
// condition was not met, flag an error
|
||||
m_context.appendInvalid();
|
||||
m_context.appendPanic(util::PanicCode::Assert);
|
||||
else if (haveReasonString)
|
||||
{
|
||||
utils().revertWithStringData(*arguments.at(1)->annotation().type);
|
||||
@ -1886,7 +1886,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
m_context << u256(fixedBytesType.numBytes());
|
||||
m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO;
|
||||
// out-of-bounds access throws exception
|
||||
m_context.appendConditionalInvalid();
|
||||
m_context.appendConditionalPanic(util::PanicCode::ArrayOutOfBounds);
|
||||
|
||||
m_context << Instruction::BYTE;
|
||||
utils().leftShiftNumberOnStack(256 - 8);
|
||||
@ -2154,7 +2154,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type cons
|
||||
{
|
||||
// Test for division by zero
|
||||
m_context << Instruction::DUP2 << Instruction::ISZERO;
|
||||
m_context.appendConditionalInvalid();
|
||||
m_context.appendConditionalPanic(util::PanicCode::DivisionByZero);
|
||||
|
||||
if (_operator == Token::Div)
|
||||
m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV);
|
||||
|
@ -122,7 +122,7 @@ string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _mess
|
||||
if iszero(condition) { <error> }
|
||||
}
|
||||
)")
|
||||
("error", _assert ? panicFunction() + "()" : "revert(0, 0)")
|
||||
("error", _assert ? panicFunction(PanicCode::Assert) + "()" : "revert(0, 0)")
|
||||
("functionName", functionName)
|
||||
.render();
|
||||
|
||||
@ -478,7 +478,7 @@ string YulUtilFunctions::overflowCheckedIntAddFunction(IntegerType const& _type)
|
||||
("maxValue", toCompactHexWithPrefix(u256(_type.maxValue())))
|
||||
("minValue", toCompactHexWithPrefix(u256(_type.minValue())))
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -530,7 +530,7 @@ string YulUtilFunctions::overflowCheckedIntMulFunction(IntegerType const& _type)
|
||||
("maxValue", toCompactHexWithPrefix(u256(_type.maxValue())))
|
||||
("minValue", toCompactHexWithPrefix(u256(_type.minValue())))
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -560,13 +560,13 @@ string YulUtilFunctions::overflowCheckedIntDivFunction(IntegerType const& _type)
|
||||
function <functionName>(x, y) -> r {
|
||||
x := <cleanupFunction>(x)
|
||||
y := <cleanupFunction>(y)
|
||||
if iszero(y) { <panic>() }
|
||||
if iszero(y) { <panicDivZero>() }
|
||||
<?signed>
|
||||
// overflow for minVal / -1
|
||||
if and(
|
||||
eq(x, <minVal>),
|
||||
eq(y, sub(0, 1))
|
||||
) { <panic>() }
|
||||
) { <panicOverflow>() }
|
||||
</signed>
|
||||
r := <?signed>s</signed>div(x, y)
|
||||
}
|
||||
@ -575,7 +575,8 @@ string YulUtilFunctions::overflowCheckedIntDivFunction(IntegerType const& _type)
|
||||
("signed", _type.isSigned())
|
||||
("minVal", toCompactHexWithPrefix(u256(_type.minValue())))
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
("panic", panicFunction())
|
||||
("panicDivZero", panicFunction(PanicCode::DivisionByZero))
|
||||
("panicOverflow", panicFunction(PanicCode::UnderOverflow))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -596,7 +597,7 @@ string YulUtilFunctions::wrappingIntDivFunction(IntegerType const& _type)
|
||||
("functionName", functionName)
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
("signed", _type.isSigned())
|
||||
("error", panicFunction())
|
||||
("error", panicFunction(PanicCode::DivisionByZero))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -617,7 +618,7 @@ string YulUtilFunctions::intModFunction(IntegerType const& _type)
|
||||
("functionName", functionName)
|
||||
("signed", _type.isSigned())
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::DivisionByZero))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -647,7 +648,7 @@ string YulUtilFunctions::overflowCheckedIntSubFunction(IntegerType const& _type)
|
||||
("maxValue", toCompactHexWithPrefix(u256(_type.maxValue())))
|
||||
("minValue", toCompactHexWithPrefix(u256(_type.minValue())))
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -808,7 +809,7 @@ string YulUtilFunctions::overflowCheckedIntLiteralExpFunction(
|
||||
("exponentCleanupFunction", cleanupFunction(_exponentType))
|
||||
("needsOverflowCheck", needsOverflowCheck)
|
||||
("exponentUpperbound", to_string(exponentUpperbound))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
("base", bigint2u(baseValue).str())
|
||||
.render();
|
||||
});
|
||||
@ -866,7 +867,7 @@ string YulUtilFunctions::overflowCheckedUnsignedExpFunction()
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
("expLoop", overflowCheckedExpLoopFunction())
|
||||
("shr_1", shiftRightFunction(1))
|
||||
.render();
|
||||
@ -916,7 +917,7 @@ string YulUtilFunctions::overflowCheckedSignedExpFunction()
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
("expLoop", overflowCheckedExpLoopFunction())
|
||||
("shr_1", shiftRightFunction(1))
|
||||
.render();
|
||||
@ -957,7 +958,7 @@ string YulUtilFunctions::overflowCheckedExpLoopFunction()
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
("shr_1", shiftRightFunction(1))
|
||||
.render();
|
||||
});
|
||||
@ -1087,7 +1088,7 @@ std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type)
|
||||
}
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::ResourceError))
|
||||
("fetchLength", arrayLengthFunction(_type))
|
||||
("convertToSize", arrayConvertLengthToSize(_type))
|
||||
("dataPosition", arrayDataAreaFunction(_type))
|
||||
@ -1123,7 +1124,7 @@ string YulUtilFunctions::resizeDynamicByteArrayFunction(ArrayType const& _type)
|
||||
}
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::ResourceError))
|
||||
("extractLength", extractByteArrayLengthFunction())
|
||||
("maxArrayLength", (u256(1) << 64).str())
|
||||
("decreaseSize", decreaseByteArraySizeFunction(_type))
|
||||
@ -1266,7 +1267,7 @@ string YulUtilFunctions::storageArrayPopFunction(ArrayType const& _type)
|
||||
sstore(array, newLen)
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::EmptyArrayPop))
|
||||
("fetchLength", arrayLengthFunction(_type))
|
||||
("indexAccess", storageArrayIndexAccessFunction(_type))
|
||||
("setToZero", storageSetToZeroFunction(*_type.baseType()))
|
||||
@ -1308,7 +1309,7 @@ string YulUtilFunctions::storageByteArrayPopFunction(ArrayType const& _type)
|
||||
}
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::EmptyArrayPop))
|
||||
("extractByteArrayLength", extractByteArrayLengthFunction())
|
||||
("transitLongToShort", byteArrayTransitLongToShortFunction(_type))
|
||||
("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction())
|
||||
@ -1370,7 +1371,7 @@ string YulUtilFunctions::storageArrayPushFunction(ArrayType const& _type)
|
||||
</isByteArray>
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::ResourceError))
|
||||
("extractByteArrayLength", _type.isByteArray() ? extractByteArrayLengthFunction() : "")
|
||||
("dataAreaFunction", arrayDataAreaFunction(_type))
|
||||
("isByteArray", _type.isByteArray())
|
||||
@ -1400,7 +1401,7 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type)
|
||||
slot, offset := <indexAccess>(array, oldLen)
|
||||
})")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::ResourceError))
|
||||
("fetchLength", arrayLengthFunction(_type))
|
||||
("indexAccess", storageArrayIndexAccessFunction(_type))
|
||||
("maxArrayLength", (u256(1) << 64).str())
|
||||
@ -1715,7 +1716,7 @@ string YulUtilFunctions::arrayAllocationSizeFunction(ArrayType const& _type)
|
||||
}
|
||||
)");
|
||||
w("functionName", functionName);
|
||||
w("panic", panicFunction());
|
||||
w("panic", panicFunction(PanicCode::ResourceError));
|
||||
w("byteArray", _type.isByteArray());
|
||||
w("dynamic", _type.isDynamicallySized());
|
||||
return w.render();
|
||||
@ -1786,7 +1787,7 @@ string YulUtilFunctions::storageArrayIndexAccessFunction(ArrayType const& _type)
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::ArrayOutOfBounds))
|
||||
("arrayLen", arrayLengthFunction(_type))
|
||||
("dataAreaFunc", arrayDataAreaFunction(_type))
|
||||
("multipleItemsPerSlot", _type.baseType()->storageBytes() <= 16)
|
||||
@ -1816,7 +1817,7 @@ string YulUtilFunctions::memoryArrayIndexAccessFunction(ArrayType const& _type)
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::ArrayOutOfBounds))
|
||||
("arrayLen", arrayLengthFunction(_type))
|
||||
("stride", to_string(_type.memoryStride()))
|
||||
("dynamicallySized", _type.isDynamicallySized())
|
||||
@ -1839,7 +1840,7 @@ string YulUtilFunctions::calldataArrayIndexAccessFunction(ArrayType const& _type
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::ArrayOutOfBounds))
|
||||
("stride", to_string(_type.calldataStride()))
|
||||
("dynamicallySized", _type.isDynamicallySized())
|
||||
("dynamicallyEncodedBase", _type.baseType()->isDynamicallyEncoded())
|
||||
@ -2509,7 +2510,7 @@ string YulUtilFunctions::allocationFunction()
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("freeMemoryPointer", to_string(CompilerUtils::freeMemoryPointer))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::ResourceError))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -3085,10 +3086,7 @@ string YulUtilFunctions::validatorFunction(Type const& _type, bool _revertOnFail
|
||||
}
|
||||
)");
|
||||
templ("functionName", functionName);
|
||||
if (_revertOnFailure)
|
||||
templ("failure", "revert(0, 0)");
|
||||
else
|
||||
templ("failure", panicFunction() + "()");
|
||||
PanicCode panicCode = PanicCode::Generic;
|
||||
|
||||
switch (_type.category())
|
||||
{
|
||||
@ -3111,6 +3109,7 @@ string YulUtilFunctions::validatorFunction(Type const& _type, bool _revertOnFail
|
||||
{
|
||||
size_t members = dynamic_cast<EnumType const&>(_type).numberOfMembers();
|
||||
solAssert(members > 0, "empty enum should have caused a parser error.");
|
||||
panicCode = PanicCode::EnumConversionError;
|
||||
templ("condition", "lt(value, " + to_string(members) + ")");
|
||||
break;
|
||||
}
|
||||
@ -3121,6 +3120,11 @@ string YulUtilFunctions::validatorFunction(Type const& _type, bool _revertOnFail
|
||||
solAssert(false, "Validation of type " + _type.identifier() + " requested.");
|
||||
}
|
||||
|
||||
if (_revertOnFailure)
|
||||
templ("failure", "revert(0, 0)");
|
||||
else
|
||||
templ("failure", panicFunction(panicCode) + "()");
|
||||
|
||||
return templ.render();
|
||||
});
|
||||
}
|
||||
@ -3196,7 +3200,7 @@ std::string YulUtilFunctions::decrementCheckedFunction(Type const& _type)
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
("minval", toCompactHexWithPrefix(type.min()))
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
.render();
|
||||
@ -3237,7 +3241,7 @@ std::string YulUtilFunctions::incrementCheckedFunction(Type const& _type)
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("maxval", toCompactHexWithPrefix(type.max()))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
.render();
|
||||
});
|
||||
@ -3278,7 +3282,7 @@ string YulUtilFunctions::negateNumberCheckedFunction(Type const& _type)
|
||||
("functionName", functionName)
|
||||
("minval", toCompactHexWithPrefix(type.min()))
|
||||
("cleanupFunction", cleanupFunction(_type))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::UnderOverflow))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -3400,7 +3404,7 @@ string YulUtilFunctions::storageSetToZeroFunction(Type const& _type)
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("clearArray", clearStorageArrayFunction(dynamic_cast<ArrayType const&>(_type)))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::Generic))
|
||||
.render();
|
||||
else if (_type.category() == Type::Category::Struct)
|
||||
return Whiskers(R"(
|
||||
@ -3411,7 +3415,7 @@ string YulUtilFunctions::storageSetToZeroFunction(Type const& _type)
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("clearStruct", clearStorageStructFunction(dynamic_cast<StructType const&>(_type)))
|
||||
("panic", panicFunction())
|
||||
("panic", panicFunction(PanicCode::Generic))
|
||||
.render();
|
||||
else
|
||||
solUnimplemented("setToZero for type " + _type.identifier() + " not yet implemented!");
|
||||
@ -3645,16 +3649,20 @@ string YulUtilFunctions::revertReasonIfDebug(string const& _message)
|
||||
return revertReasonIfDebug(m_revertStrings, _message);
|
||||
}
|
||||
|
||||
string YulUtilFunctions::panicFunction()
|
||||
string YulUtilFunctions::panicFunction(util::PanicCode _code)
|
||||
{
|
||||
string functionName = "panic_error";
|
||||
string functionName = "panic_error_" + toCompactHexWithPrefix(uint64_t(_code));
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
return Whiskers(R"(
|
||||
function <functionName>() {
|
||||
invalid()
|
||||
mstore(0, <selector>)
|
||||
mstore(4, <code>)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("selector", util::selectorFromSignature("Panic(uint256)").str())
|
||||
("code", toCompactHexWithPrefix(_code))
|
||||
.render();
|
||||
});
|
||||
}
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
#include <libsolidity/interface/DebugSettings.h>
|
||||
|
||||
#include <libsolutil/ErrorCodes.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -406,9 +408,8 @@ public:
|
||||
|
||||
std::string revertReasonIfDebug(std::string const& _message = "");
|
||||
|
||||
/// Executes the invalid opcode.
|
||||
/// Might use revert with special error code in the future.
|
||||
std::string panicFunction();
|
||||
/// Reverts with ``Panic(uint256)`` and the given code.
|
||||
std::string panicFunction(util::PanicCode _code);
|
||||
|
||||
/// Returns the name of a function that decodes an error message.
|
||||
/// signature: () -> arrayPtr
|
||||
|
@ -208,7 +208,7 @@ InternalDispatchMap IRGenerator::generateInternalDispatchFunctions()
|
||||
}
|
||||
)");
|
||||
templ("functionName", funName);
|
||||
templ("panic", m_utils.panicFunction());
|
||||
templ("panic", m_utils.panicFunction(PanicCode::InvalidInternalFunction));
|
||||
templ("in", suffixedVariableNameList("in_", 0, arity.in));
|
||||
templ("out", suffixedVariableNameList("out_", 0, arity.out));
|
||||
|
||||
|
@ -1302,7 +1302,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
define(modulus, *arguments[2]);
|
||||
Whiskers templ("if iszero(<modulus>) { <panic>() }\n");
|
||||
templ("modulus", modulus.name());
|
||||
templ("panic", m_utils.panicFunction());
|
||||
templ("panic", m_utils.panicFunction(PanicCode::DivisionByZero));
|
||||
m_code << templ.render();
|
||||
|
||||
string args;
|
||||
@ -1367,7 +1367,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
t("allocateTemporaryMemory", m_utils.allocationTemporaryMemoryFunction());
|
||||
t("releaseTemporaryMemory", m_utils.releaseTemporaryMemoryFunction());
|
||||
t("object", IRNames::creationObject(*contract));
|
||||
t("panic", m_utils.panicFunction());
|
||||
t("panic", m_utils.panicFunction(PanicCode::ResourceError));
|
||||
t("abiEncode",
|
||||
m_context.abiFunctions().tupleEncoder(argumentTypes, functionType->parameterTypes(), false)
|
||||
);
|
||||
@ -2023,7 +2023,7 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
)")
|
||||
("index", index.name())
|
||||
("length", to_string(fixedBytesType.numBytes()))
|
||||
("panic", m_utils.panicFunction())
|
||||
("panic", m_utils.panicFunction(PanicCode::ArrayOutOfBounds))
|
||||
("array", IRVariable(_indexAccess.baseExpression()).name())
|
||||
("shl248", m_utils.shiftLeftFunction(256 - 8))
|
||||
("result", IRVariable(_indexAccess).name())
|
||||
|
@ -9,6 +9,7 @@ set(sources
|
||||
CommonIO.h
|
||||
Exceptions.cpp
|
||||
Exceptions.h
|
||||
ErrorCodes.h
|
||||
FixedHash.h
|
||||
FunctionSelector.h
|
||||
IndentedWriter.cpp
|
||||
|
38
libsolutil/ErrorCodes.h
Normal file
38
libsolutil/ErrorCodes.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace solidity::util
|
||||
{
|
||||
|
||||
enum class PanicCode
|
||||
{
|
||||
Generic = 0x00, // generic / unspecified error.
|
||||
Assert = 0x01, // generic / unspecified error. Used by assert().
|
||||
UnderOverflow = 0x11, // arithmetic underflow or overflow
|
||||
DivisionByZero = 0x12, // division or modulo by zero
|
||||
EnumConversionError = 0x21, // enum conversion error
|
||||
EmptyArrayPop = 0x31, // empty array pop
|
||||
ArrayOutOfBounds = 0x32, // array out of bounds access
|
||||
ResourceError = 0x41, // resource error (too large allocation or too large array)
|
||||
InvalidInternalFunction = 0x51, // calling invalid internal function
|
||||
};
|
||||
|
||||
}
|
@ -378,6 +378,7 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA
|
||||
BuiltinContext&,
|
||||
std::function<void(Expression const&)> _visitExpression
|
||||
) {
|
||||
// TODO this should use a Panic.
|
||||
// A value larger than 1 causes an invalid instruction.
|
||||
visitArguments(_assembly, _call, _visitExpression);
|
||||
_assembly.appendConstant(2);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <test/evmc/evmc.hpp>
|
||||
|
||||
#include <libsolutil/CommonIO.h>
|
||||
#include <libsolutil/FunctionSelector.h>
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
@ -112,6 +113,14 @@ std::pair<bool, string> ExecutionFramework::compareAndCreateMessage(
|
||||
return make_pair(false, message);
|
||||
}
|
||||
|
||||
bytes ExecutionFramework::panicData(util::PanicCode _code)
|
||||
{
|
||||
return
|
||||
m_evmVersion.supportsReturndata() ?
|
||||
toCompactBigEndian(selectorFromSignature32("Panic(uint256)"), 4) + encode(u256(_code)) :
|
||||
bytes();
|
||||
}
|
||||
|
||||
u256 ExecutionFramework::gasLimit() const
|
||||
{
|
||||
return {m_evmcHost->tx_context.block_gas_limit};
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <libsolutil/FixedHash.h>
|
||||
#include <libsolutil/Keccak256.h>
|
||||
#include <libsolutil/ErrorCodes.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
@ -200,6 +201,9 @@ public:
|
||||
{
|
||||
return bytes();
|
||||
}
|
||||
/// @returns error returndata corresponding to the Panic(uint256) error code,
|
||||
/// if REVERT is supported by the current EVM version and the empty string otherwise.
|
||||
bytes panicData(util::PanicCode _code);
|
||||
|
||||
//@todo might be extended in the future
|
||||
template <class Arg>
|
||||
|
@ -103,7 +103,7 @@ object "C_80" {
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
// protect against overflow
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ object "C_80" {
|
||||
function checked_exp_t_rational_10_by_1_t_uint256(exponent) -> power {
|
||||
exponent := cleanup_t_uint256(exponent)
|
||||
|
||||
if gt(exponent, 77) { panic_error() }
|
||||
if gt(exponent, 77) { panic_error_0x11() }
|
||||
|
||||
power := exp(10, exponent)
|
||||
}
|
||||
@ -124,7 +124,7 @@ object "C_80" {
|
||||
function checked_exp_t_rational_115792089237316195423570985008687907853269984665640564039457584007913129639935_by_1_t_uint256(exponent) -> power {
|
||||
exponent := cleanup_t_uint256(exponent)
|
||||
|
||||
if gt(exponent, 1) { panic_error() }
|
||||
if gt(exponent, 1) { panic_error_0x11() }
|
||||
|
||||
power := exp(115792089237316195423570985008687907853269984665640564039457584007913129639935, exponent)
|
||||
}
|
||||
@ -138,7 +138,7 @@ object "C_80" {
|
||||
function checked_exp_t_rational_2_by_1_t_uint256(exponent) -> power {
|
||||
exponent := cleanup_t_uint256(exponent)
|
||||
|
||||
if gt(exponent, 255) { panic_error() }
|
||||
if gt(exponent, 255) { panic_error_0x11() }
|
||||
|
||||
power := exp(2, exponent)
|
||||
}
|
||||
@ -152,7 +152,7 @@ object "C_80" {
|
||||
function checked_exp_t_rational_minus_2_by_1_t_uint256(exponent) -> power {
|
||||
exponent := cleanup_t_uint256(exponent)
|
||||
|
||||
if gt(exponent, 255) { panic_error() }
|
||||
if gt(exponent, 255) { panic_error_0x11() }
|
||||
|
||||
power := exp(115792089237316195423570985008687907853269984665640564039457584007913129639934, exponent)
|
||||
}
|
||||
@ -274,8 +274,16 @@ object "C_80" {
|
||||
|
||||
}
|
||||
|
||||
function panic_error() {
|
||||
invalid()
|
||||
function panic_error_0x11() {
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x11)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
function panic_error_0x41() {
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
function shift_right_224_unsigned(value) -> newValue {
|
||||
|
@ -57,7 +57,7 @@ object "D_15" {
|
||||
if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) }
|
||||
let _2 := datasize("C_2")
|
||||
let _3 := add(128, _2)
|
||||
if or(gt(_3, 0xffffffffffffffff), lt(_3, 128)) { invalid() }
|
||||
if or(gt(_3, 0xffffffffffffffff), lt(_3, 128)) { panic_error_0x41() }
|
||||
datacopy(128, dataoffset("C_2"), _2)
|
||||
pop(create(_1, 128, _2))
|
||||
return(allocateMemory(_1), _1)
|
||||
@ -69,9 +69,15 @@ object "D_15" {
|
||||
{
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { invalid() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
function panic_error_0x41()
|
||||
{
|
||||
mstore(0, shl(224, 0x4e487b71))
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
}
|
||||
object "C_2" {
|
||||
code {
|
||||
|
@ -33,7 +33,7 @@ object "C_59" {
|
||||
if gt(offset, _3) { revert(_1, _1) }
|
||||
if iszero(slt(add(offset, 35), calldatasize())) { revert(_1, _1) }
|
||||
let length := calldataload(add(4, offset))
|
||||
if gt(length, _3) { invalid() }
|
||||
if gt(length, _3) { panic_error_0x41() }
|
||||
let _4 := mul(length, _2)
|
||||
let dst := allocateMemory(add(_4, _2))
|
||||
let dst_1 := dst
|
||||
@ -60,7 +60,7 @@ object "C_59" {
|
||||
if slt(sub(end, headStart), 0x20) { revert(value, value) }
|
||||
let memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, 0x20)
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { invalid() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
value := memPtr
|
||||
mstore(memPtr, calldataload(headStart))
|
||||
@ -87,14 +87,14 @@ object "C_59" {
|
||||
{
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { invalid() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
function convert_t_stringliteral_6490_to_t_string() -> converted
|
||||
{
|
||||
let memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, 160)
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { invalid() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
converted := memPtr
|
||||
mstore(memPtr, 100)
|
||||
@ -109,26 +109,37 @@ object "C_59" {
|
||||
}
|
||||
function fun_sumArray_58(vloc__s_22_mpos) -> vloc, vloc__27_mpos
|
||||
{
|
||||
let _1 := mload(vloc__s_22_mpos)
|
||||
if iszero(lt(vloc, _1)) { invalid() }
|
||||
let _2 := mload(mload(add(add(vloc__s_22_mpos, mul(vloc, 32)), 32)))
|
||||
let _3, _4 := storage_array_index_access$_t_struct$_S_storage(vloc, vloc)
|
||||
sstore(_3, _2)
|
||||
if iszero(lt(0x01, _1)) { invalid() }
|
||||
let _5 := mload(mload(add(vloc__s_22_mpos, 64)))
|
||||
if iszero(lt(vloc, 0x02)) { invalid() }
|
||||
if iszero(lt(vloc, mload(vloc__s_22_mpos))) { panic_error_0x32() }
|
||||
let _1 := mload(mload(add(add(vloc__s_22_mpos, mul(vloc, 32)), 32)))
|
||||
let _2, _3 := storage_array_index_access$_t_struct$_S_storage(vloc, vloc)
|
||||
sstore(_2, _1)
|
||||
if iszero(lt(0x01, mload(vloc__s_22_mpos))) { panic_error_0x32() }
|
||||
let _4 := mload(mload(add(vloc__s_22_mpos, 64)))
|
||||
if iszero(lt(vloc, 0x02)) { panic_error_0x32() }
|
||||
let slot := add(0x02, vloc)
|
||||
let _6 := sload(slot)
|
||||
let _5 := sload(slot)
|
||||
let shiftBits := mul(vloc, 8)
|
||||
let mask := shl(shiftBits, not(0))
|
||||
sstore(slot, or(and(_6, not(mask)), and(shl(shiftBits, _5), mask)))
|
||||
let _7, _8 := storage_array_index_access$_t_struct$_S_storage(0x02, vloc)
|
||||
vloc := extract_from_storage_value_dynamict_uint256(sload(_7), _8)
|
||||
sstore(slot, or(and(_5, not(mask)), and(shl(shiftBits, _4), mask)))
|
||||
let _6, _7 := storage_array_index_access$_t_struct$_S_storage(0x02, vloc)
|
||||
vloc := extract_from_storage_value_dynamict_uint256(sload(_6), _7)
|
||||
vloc__27_mpos := convert_t_stringliteral_6490_to_t_string()
|
||||
}
|
||||
function panic_error_0x32()
|
||||
{
|
||||
mstore(0, shl(224, 0x4e487b71))
|
||||
mstore(4, 0x32)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
function panic_error_0x41()
|
||||
{
|
||||
mstore(0, shl(224, 0x4e487b71))
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
function storage_array_index_access$_t_struct$_S_storage(array, index) -> slot, offset
|
||||
{
|
||||
if iszero(lt(index, 0x02)) { invalid() }
|
||||
if iszero(lt(index, 0x02)) { panic_error_0x32() }
|
||||
slot := add(array, index)
|
||||
offset := offset
|
||||
}
|
||||
|
@ -33,14 +33,12 @@ object "Arraysum_33" {
|
||||
for { }
|
||||
lt(vloc_i, _2)
|
||||
{
|
||||
if eq(vloc_i, not(0)) { invalid() }
|
||||
if eq(vloc_i, not(0)) { panic_error_0x11() }
|
||||
vloc_i := add(vloc_i, 1)
|
||||
}
|
||||
{
|
||||
mstore(_1, _1)
|
||||
let _3 := sload(add(keccak256(_1, 0x20), vloc_i))
|
||||
if gt(vloc_sum, not(_3)) { invalid() }
|
||||
vloc_sum := add(vloc_sum, _3)
|
||||
vloc_sum := checked_add_t_uint256(vloc_sum, sload(add(keccak256(_1, 0x20), vloc_i)))
|
||||
}
|
||||
let memPos := allocateMemory(_1)
|
||||
return(memPos, sub(abi_encode_uint(memPos, vloc_sum), memPos))
|
||||
@ -57,9 +55,25 @@ object "Arraysum_33" {
|
||||
{
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { invalid() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr))
|
||||
{
|
||||
mstore(0, shl(224, 0x4e487b71))
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
function checked_add_t_uint256(x, y) -> sum
|
||||
{
|
||||
if gt(x, not(y)) { panic_error_0x11() }
|
||||
sum := add(x, y)
|
||||
}
|
||||
function panic_error_0x11()
|
||||
{
|
||||
mstore(0, shl(224, 0x4e487b71))
|
||||
mstore(4, 0x11)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -44,13 +44,17 @@ object \"C_6\" {
|
||||
{
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
function fun_f_5()
|
||||
{ }
|
||||
function panic_error()
|
||||
{ invalid() }
|
||||
function panic_error_0x41()
|
||||
{
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
function shift_right_224_unsigned(value) -> newValue
|
||||
{ newValue := shr(224, value) }
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ object \"C_6\" {
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
// protect against overflow
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
|
||||
@ -69,8 +69,10 @@ object \"C_6\" {
|
||||
|
||||
}
|
||||
|
||||
function panic_error() {
|
||||
invalid()
|
||||
function panic_error_0x41() {
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
function shift_right_224_unsigned(value) -> newValue {
|
||||
|
File diff suppressed because one or more lines are too long
@ -71,7 +71,7 @@ object \"C_10\" {
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
// protect against overflow
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
|
||||
@ -116,8 +116,10 @@ object \"C_10\" {
|
||||
|
||||
}
|
||||
|
||||
function panic_error() {
|
||||
invalid()
|
||||
function panic_error_0x41() {
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
function round_up_to_mul_of_32(value) -> result {
|
||||
|
@ -67,7 +67,7 @@ object \"C_10\" {
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
// protect against overflow
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
|
||||
@ -88,8 +88,10 @@ object \"C_10\" {
|
||||
|
||||
}
|
||||
|
||||
function panic_error() {
|
||||
invalid()
|
||||
function panic_error_0x41() {
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
function shift_right_224_unsigned(value) -> newValue {
|
||||
|
@ -67,7 +67,7 @@ object \"C_10\" {
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
// protect against overflow
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
|
||||
@ -93,8 +93,10 @@ object \"C_10\" {
|
||||
|
||||
}
|
||||
|
||||
function panic_error() {
|
||||
invalid()
|
||||
function panic_error_0x41() {
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
function shift_left_224(value) -> newValue {
|
||||
|
@ -71,7 +71,7 @@ object \"C_10\" {
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
// protect against overflow
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
|
||||
@ -120,8 +120,10 @@ object \"C_10\" {
|
||||
|
||||
}
|
||||
|
||||
function panic_error() {
|
||||
invalid()
|
||||
function panic_error_0x41() {
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
function round_up_to_mul_of_32(value) -> result {
|
||||
|
@ -67,7 +67,7 @@ object \"C_10\" {
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, size)
|
||||
// protect against overflow
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error() }
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
|
||||
@ -93,8 +93,10 @@ object \"C_10\" {
|
||||
|
||||
}
|
||||
|
||||
function panic_error() {
|
||||
invalid()
|
||||
function panic_error_0x41() {
|
||||
mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
|
||||
function shift_left_224(value) -> newValue {
|
||||
|
@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(enum_type_cleanup)
|
||||
compileAndRun(sourceCode);
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", 0) == encodeArgs(0));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", 1) == encodeArgs(1));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", 2) == encodeArgs());
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", 2) == panicData(PanicCode::EnumConversionError));
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -201,8 +201,12 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
|
||||
);
|
||||
}
|
||||
|
||||
if ((m_transactionSuccessful == test.call().expectations.failure)
|
||||
|| (output != test.call().expectations.rawBytes()))
|
||||
bool outputMismatch = (output != test.call().expectations.rawBytes());
|
||||
// Pre byzantium, it was not possible to return failure data, so we disregard
|
||||
// output mismatch for those EVM versions.
|
||||
if (test.call().expectations.failure && !m_transactionSuccessful && !m_evmVersion.supportsReturndata())
|
||||
outputMismatch = false;
|
||||
if (m_transactionSuccessful != !test.call().expectations.failure || outputMismatch)
|
||||
success = false;
|
||||
|
||||
test.setFailure(!m_transactionSuccessful);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <libevmasm/Assembly.h>
|
||||
|
||||
#include <libsolutil/Keccak256.h>
|
||||
#include <libsolutil/ErrorCodes.h>
|
||||
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@ -2554,7 +2555,7 @@ BOOST_AUTO_TEST_CASE(generic_staticcall)
|
||||
ABI_CHECK(callContractFunction("g(address)", c_addressA), encodeArgs(true, 0x40, 0x20, 23 + 42));
|
||||
ABI_CHECK(callContractFunction("h(address)", c_addressA), encodeArgs(false, 0x40, 0x00));
|
||||
ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 42), encodeArgs(true, 0x40, 0x20, 42));
|
||||
ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 23), encodeArgs(false, 0x40, 0x00));
|
||||
ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 23), encodeArgs(false, 0x40, 0x24) + panicData(PanicCode::Assert) + bytes(32 - 4, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3678,8 +3679,7 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged)
|
||||
BOOST_REQUIRE_EQUAL(logTopic(0, 0), util::keccak256(string("Log(uint8)")));
|
||||
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(0)));
|
||||
|
||||
// should throw
|
||||
ABI_CHECK(callContractFunction("test_log()"), encodeArgs());
|
||||
ABI_CHECK(callContractFunction("test_log()"), panicData(PanicCode::EnumConversionError));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund)
|
||||
@ -3696,7 +3696,7 @@ BOOST_AUTO_TEST_CASE(evm_exceptions_in_constructor_out_of_baund)
|
||||
}
|
||||
}
|
||||
)";
|
||||
ABI_CHECK(compileAndRunWithoutCheck({{"", sourceCode}}, 0, "A"), encodeArgs());
|
||||
ABI_CHECK(compileAndRunWithoutCheck({{"", sourceCode}}, 0, "A"), panicData(PanicCode::ArrayOutOfBounds));
|
||||
BOOST_CHECK(!m_transactionSuccessful);
|
||||
}
|
||||
|
||||
@ -4176,7 +4176,7 @@ BOOST_AUTO_TEST_CASE(calldata_bytes_array_bounds)
|
||||
);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes[],uint256)", 0x40, 2, 1, 0x20, 2, bytes{'a', 'b'} + bytes(30, 0)),
|
||||
encodeArgs()
|
||||
panicData(PanicCode::ArrayOutOfBounds)
|
||||
);
|
||||
}
|
||||
|
||||
@ -4226,11 +4226,9 @@ BOOST_AUTO_TEST_CASE(calldata_array_two_dimensional)
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, j, encoding), encodeArgs(data[i][j]));
|
||||
ABI_CHECK(callContractFunction("reenc(" + arrayType + ",uint256,uint256)", 0x60, i, j, encoding), encodeArgs(data[i][j]));
|
||||
}
|
||||
// out of bounds access
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, data[i].size(), encoding), encodeArgs());
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, data[i].size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
|
||||
}
|
||||
// out of bounds access
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, data.size(), encoding), encodeArgs());
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, data.size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4308,14 +4306,11 @@ BOOST_AUTO_TEST_CASE(calldata_array_dynamic_three_dimensional)
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256,uint256)", 0x80, i, j, k, encoding), encodeArgs(data[i][j][k]));
|
||||
ABI_CHECK(callContractFunction("reenc(" + arrayType + ",uint256,uint256,uint256)", 0x80, i, j, k, encoding), encodeArgs(data[i][j][k]));
|
||||
}
|
||||
// out of bounds access
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256,uint256)", 0x80, i, j, data[i][j].size(), encoding), encodeArgs());
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256,uint256)", 0x80, i, j, data[i][j].size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
|
||||
}
|
||||
// out of bounds access
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, data[i].size(), encoding), encodeArgs());
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, data[i].size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
|
||||
}
|
||||
// out of bounds access
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, data.size(), encoding), encodeArgs());
|
||||
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, data.size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,9 +327,23 @@ BOOST_AUTO_TEST_CASE(arithmetic)
|
||||
)";
|
||||
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
|
||||
|
||||
bytes panic =
|
||||
bytes{uint8_t(Instruction::PUSH32)} +
|
||||
fromHex("4E487B7100000000000000000000000000000000000000000000000000000000") +
|
||||
bytes{
|
||||
uint8_t(Instruction::PUSH1), 0x0,
|
||||
uint8_t(Instruction::MSTORE),
|
||||
uint8_t(Instruction::PUSH1), 0x12,
|
||||
uint8_t(Instruction::PUSH1), 0x4,
|
||||
uint8_t(Instruction::MSTORE),
|
||||
uint8_t(Instruction::PUSH1), 0x24,
|
||||
uint8_t(Instruction::PUSH1), 0x0,
|
||||
uint8_t(Instruction::REVERT)
|
||||
};
|
||||
|
||||
bytes expectation;
|
||||
if (solidity::test::CommonOptions::get().optimize)
|
||||
expectation = {
|
||||
expectation = bytes{
|
||||
uint8_t(Instruction::PUSH1), 0x2,
|
||||
uint8_t(Instruction::PUSH1), 0x3,
|
||||
uint8_t(Instruction::PUSH1), 0x5,
|
||||
@ -346,24 +360,24 @@ BOOST_AUTO_TEST_CASE(arithmetic)
|
||||
uint8_t(Instruction::DUP2),
|
||||
uint8_t(Instruction::ISZERO),
|
||||
uint8_t(Instruction::ISZERO),
|
||||
uint8_t(Instruction::PUSH1), 0x1b,
|
||||
uint8_t(Instruction::JUMPI),
|
||||
uint8_t(Instruction::INVALID),
|
||||
uint8_t(Instruction::PUSH1), 0x48,
|
||||
uint8_t(Instruction::JUMPI)
|
||||
} + panic + bytes{
|
||||
uint8_t(Instruction::JUMPDEST),
|
||||
uint8_t(Instruction::MOD),
|
||||
uint8_t(Instruction::DUP2),
|
||||
uint8_t(Instruction::ISZERO),
|
||||
uint8_t(Instruction::ISZERO),
|
||||
uint8_t(Instruction::PUSH1), 0x24,
|
||||
uint8_t(Instruction::JUMPI),
|
||||
uint8_t(Instruction::INVALID),
|
||||
uint8_t(Instruction::PUSH1), 0x7e,
|
||||
uint8_t(Instruction::JUMPI)
|
||||
} + panic + bytes{
|
||||
uint8_t(Instruction::JUMPDEST),
|
||||
uint8_t(Instruction::DIV),
|
||||
uint8_t(Instruction::PUSH1), 0x1,
|
||||
uint8_t(Instruction::MUL)
|
||||
};
|
||||
else
|
||||
expectation = {
|
||||
expectation = bytes{
|
||||
uint8_t(Instruction::PUSH1), 0x1,
|
||||
uint8_t(Instruction::PUSH1), 0x2,
|
||||
uint8_t(Instruction::PUSH1), 0x3,
|
||||
@ -381,21 +395,22 @@ BOOST_AUTO_TEST_CASE(arithmetic)
|
||||
uint8_t(Instruction::DUP2),
|
||||
uint8_t(Instruction::ISZERO),
|
||||
uint8_t(Instruction::ISZERO),
|
||||
uint8_t(Instruction::PUSH1), 0x1d,
|
||||
uint8_t(Instruction::JUMPI),
|
||||
uint8_t(Instruction::INVALID),
|
||||
uint8_t(Instruction::PUSH1), 0x4a,
|
||||
uint8_t(Instruction::JUMPI)
|
||||
} + panic + bytes{
|
||||
uint8_t(Instruction::JUMPDEST),
|
||||
uint8_t(Instruction::MOD),
|
||||
uint8_t(Instruction::DUP2),
|
||||
uint8_t(Instruction::ISZERO),
|
||||
uint8_t(Instruction::ISZERO),
|
||||
uint8_t(Instruction::PUSH1), 0x26,
|
||||
uint8_t(Instruction::JUMPI),
|
||||
uint8_t(Instruction::INVALID),
|
||||
uint8_t(Instruction::PUSH1), 0x80,
|
||||
uint8_t(Instruction::JUMPI)
|
||||
} + panic + bytes{
|
||||
uint8_t(Instruction::JUMPDEST),
|
||||
uint8_t(Instruction::DIV),
|
||||
uint8_t(Instruction::MUL)
|
||||
};
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,9 @@ contract C {
|
||||
}
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 1107400
|
||||
// executionCost: 1154
|
||||
// totalCost: 1108554
|
||||
// codeDepositCost: 1116400
|
||||
// executionCost: 1160
|
||||
// totalCost: 1117560
|
||||
// external:
|
||||
// a(): 1130
|
||||
// b(uint256): infinite
|
||||
|
@ -17,9 +17,9 @@ contract C {
|
||||
// optimize-yul: true
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 605000
|
||||
// executionCost: 638
|
||||
// totalCost: 605638
|
||||
// codeDepositCost: 615400
|
||||
// executionCost: 651
|
||||
// totalCost: 616051
|
||||
// external:
|
||||
// a(): 1029
|
||||
// b(uint256): 2084
|
||||
|
@ -24,9 +24,9 @@ contract Large {
|
||||
}
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 637600
|
||||
// executionCost: 670
|
||||
// totalCost: 638270
|
||||
// codeDepositCost: 961600
|
||||
// executionCost: 1001
|
||||
// totalCost: 962601
|
||||
// external:
|
||||
// a(): 1051
|
||||
// b(uint256): 2046
|
||||
|
@ -27,9 +27,9 @@ contract Large {
|
||||
// optimize-runs: 2
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 261200
|
||||
// executionCost: 300
|
||||
// totalCost: 261500
|
||||
// codeDepositCost: 301200
|
||||
// executionCost: 343
|
||||
// totalCost: 301543
|
||||
// external:
|
||||
// a(): 998
|
||||
// b(uint256): 2305
|
||||
|
@ -11,9 +11,9 @@ contract Medium {
|
||||
}
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 253800
|
||||
// executionCost: 294
|
||||
// totalCost: 254094
|
||||
// codeDepositCost: 361800
|
||||
// executionCost: 399
|
||||
// totalCost: 362199
|
||||
// external:
|
||||
// a(): 1028
|
||||
// b(uint256): 2046
|
||||
|
@ -14,9 +14,9 @@ contract Medium {
|
||||
// optimize-runs: 2
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 141600
|
||||
// executionCost: 190
|
||||
// totalCost: 141790
|
||||
// codeDepositCost: 169600
|
||||
// executionCost: 214
|
||||
// totalCost: 169814
|
||||
// external:
|
||||
// a(): 998
|
||||
// b(uint256): 2063
|
||||
|
@ -6,9 +6,9 @@ contract Small {
|
||||
}
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 85400
|
||||
// executionCost: 135
|
||||
// totalCost: 85535
|
||||
// codeDepositCost: 103400
|
||||
// executionCost: 153
|
||||
// totalCost: 103553
|
||||
// external:
|
||||
// fallback: 129
|
||||
// a(): 983
|
||||
|
@ -9,9 +9,9 @@ contract Small {
|
||||
// optimize-runs: 2
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 61200
|
||||
// executionCost: 111
|
||||
// totalCost: 61311
|
||||
// codeDepositCost: 72800
|
||||
// executionCost: 123
|
||||
// totalCost: 72923
|
||||
// external:
|
||||
// fallback: 118
|
||||
// a(): 976
|
||||
|
@ -21,6 +21,6 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(uint256): 0 -> FAILURE
|
||||
// g(uint256): 0 -> FAILURE
|
||||
// f(uint256): 0 -> FAILURE, hex"4e487b71", 0x12
|
||||
// g(uint256): 0 -> FAILURE, hex"4e487b71", 0x12
|
||||
// h() -> 2
|
||||
|
@ -14,5 +14,5 @@ contract D {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> FAILURE
|
||||
// f() -> FAILURE, hex"4e487b71", 0x11
|
||||
// g(), 100 wei -> 1
|
||||
|
@ -10,4 +10,4 @@ contract C {
|
||||
// f(uint16,uint16): 65534, 0 -> 0xfffe
|
||||
// f(uint16,uint16): 65536, 0 -> 0x00
|
||||
// f(uint16,uint16): 65535, 0 -> 0xffff
|
||||
// f(uint16,uint16): 65535, 1 -> FAILURE
|
||||
// f(uint16,uint16): 65535, 1 -> FAILURE, hex"4e487b71", 0x11
|
||||
|
@ -10,5 +10,5 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(uint16,uint16,uint16): 0xe000, 0xe500, 2 -> FAILURE
|
||||
// f(uint16,uint16,uint16): 0xe000, 0xe500, 2 -> FAILURE, hex"4e487b71", 0x11
|
||||
// f(uint16,uint16,uint16): 0xe000, 0x1000, 0x1000 -> 0x00
|
||||
|
@ -12,4 +12,4 @@ contract C {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f(uint16,uint16,uint16): 0xe000, 0xe500, 2 -> 58626
|
||||
// f(uint16,uint16,uint16): 0x1000, 0xe500, 0xe000 -> FAILURE
|
||||
// f(uint16,uint16,uint16): 0x1000, 0xe500, 0xe000 -> FAILURE, hex"4e487b71", 0x11
|
||||
|
@ -11,6 +11,6 @@ contract C {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// div(uint256,uint256): 7, 2 -> 3
|
||||
// div(uint256,uint256): 7, 0 -> FAILURE # throws #
|
||||
// div(uint256,uint256): 7, 0 -> FAILURE, hex"4e487b71", 0x12 # throws #
|
||||
// mod(uint256,uint256): 7, 2 -> 1
|
||||
// mod(uint256,uint256): 7, 0 -> FAILURE # throws #
|
||||
// mod(uint256,uint256): 7, 0 -> FAILURE, hex"4e487b71", 0x12 # throws #
|
||||
|
@ -20,5 +20,5 @@ contract C {
|
||||
// f(int256,int256): -7, 5 -> -2
|
||||
// f(int256,int256): -7, 5 -> -2
|
||||
// f(int256,int256): -5, -5 -> 0
|
||||
// g(bool): true -> FAILURE
|
||||
// g(bool): true -> FAILURE, hex"4e487b71", 0x11
|
||||
// g(bool): false -> -57896044618658097711785492504343953926634992332820282019728792003956564819968
|
||||
|
@ -14,4 +14,4 @@ contract C {
|
||||
// ----
|
||||
// f(uint16): 7 -> 0x0207
|
||||
// f(uint16): 0xffff -> 511
|
||||
// f(uint16): 0xfeff -> FAILURE
|
||||
// f(uint16): 0xfeff -> FAILURE, hex"4e487b71", 0x11
|
||||
|
@ -17,6 +17,6 @@ contract C {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// div(uint256,uint256): 7, 2 -> 3
|
||||
// div(uint256,uint256): 7, 0 -> FAILURE # throws #
|
||||
// div(uint256,uint256): 7, 0 -> FAILURE, hex"4e487b71", 0x12 # throws #
|
||||
// mod(uint256,uint256): 7, 2 -> 1
|
||||
// mod(uint256,uint256): 7, 0 -> FAILURE # throws #
|
||||
// mod(uint256,uint256): 7, 0 -> FAILURE, hex"4e487b71", 0x12 # throws #
|
||||
|
@ -9,4 +9,4 @@ contract c {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> FAILURE
|
||||
// test() -> FAILURE, hex"4e487b71", 0x31
|
||||
|
@ -12,4 +12,4 @@ contract c {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> FAILURE
|
||||
// test() -> FAILURE, hex"4e487b71", 0x31
|
||||
|
@ -24,23 +24,23 @@ contract C {
|
||||
// f(uint256[],uint256,uint256): 0x80, -1, 0, 0, 1, 42 -> FAILURE
|
||||
// f(uint256[],uint256,uint256): 0x80, -1, -1, 0, 1, 42 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 0, 1, 42 -> 42, 42, 42
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 1, 1, 42 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 0, 0, 1, 42 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 1, 0, 1, 42 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 1, 1, 42 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 0, 0, 1, 42 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 1, 0, 1, 42 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 5, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4201, 0x4201, 0x4201
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 5, 4, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4205, 0x4205, 0x4205
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 5, 5, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 5, 5, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 5, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4202, 0x4202, 0x4202
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 5, 3, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4205, 0x4205, 0x4205
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 5, 4, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 5, 4, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 4, 5, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4205, 0x4205, 0x4205
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 4, 5, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 5, 5, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 4, 5, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 5, 5, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4201, 0x4201, 0x4201
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4201, 0x4201, 0x4201
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 0, 1, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 2, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4202, 0x4202, 0x4202
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 2, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 1, 2, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE, hex"4e487b71", 0x32
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 4, 5, 0, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> 0x4205, 0x4205, 0x4205
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 4, 5, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE
|
||||
// g(uint256[],uint256,uint256,uint256): 0x80, 4, 5, 1, 5, 0x4201, 0x4202, 0x4203, 0x4204, 0x4205 -> FAILURE, hex"4e487b71", 0x32
|
||||
|
@ -19,4 +19,4 @@ contract C {
|
||||
|
||||
// ----
|
||||
// one() -> 3
|
||||
// two() -> FAILURE
|
||||
// two() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -22,5 +22,5 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> FAILURE
|
||||
// g() -> FAILURE
|
||||
// f() -> FAILURE, hex"4e487b71", 0x41
|
||||
// g() -> FAILURE, hex"4e487b71", 0x41
|
||||
|
@ -24,11 +24,11 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// length() -> 0
|
||||
// get(uint256): 3 -> FAILURE
|
||||
// get(uint256): 3 -> FAILURE, hex"4e487b71", 0x32
|
||||
// enlarge(uint256): 4 -> 4
|
||||
// length() -> 4
|
||||
// set(uint256,uint256): 3, 4 -> true
|
||||
// get(uint256): 3 -> 4
|
||||
// length() -> 4
|
||||
// set(uint256,uint256): 4, 8 -> FAILURE
|
||||
// set(uint256,uint256): 4, 8 -> FAILURE, hex"4e487b71", 0x32
|
||||
// length() -> 4
|
||||
|
@ -16,5 +16,5 @@ contract A {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> false
|
||||
// testIt() -> FAILURE
|
||||
// testIt() -> FAILURE, hex"4e487b71", 0x32
|
||||
// test() -> false
|
||||
|
@ -20,9 +20,9 @@ contract c {
|
||||
// ----
|
||||
// length() -> 4
|
||||
// set(uint256,uint256): 3, 4 -> true
|
||||
// set(uint256,uint256): 4, 5 -> FAILURE
|
||||
// set(uint256,uint256): 400, 5 -> FAILURE
|
||||
// set(uint256,uint256): 4, 5 -> FAILURE, hex"4e487b71", 0x32
|
||||
// set(uint256,uint256): 400, 5 -> FAILURE, hex"4e487b71", 0x32
|
||||
// get(uint256): 3 -> 4
|
||||
// get(uint256): 4 -> FAILURE
|
||||
// get(uint256): 400 -> FAILURE
|
||||
// get(uint256): 4 -> FAILURE, hex"4e487b71", 0x32
|
||||
// get(uint256): 400 -> FAILURE, hex"4e487b71", 0x32
|
||||
// length() -> 4
|
||||
|
@ -38,4 +38,4 @@ contract C {
|
||||
// test(uint256,uint256): 10, 2 -> 13
|
||||
// test(uint256,uint256): 10, 3 -> 15
|
||||
// test(uint256,uint256): 10, 4 -> 18
|
||||
// test(uint256,uint256): 10, 5 -> FAILURE
|
||||
// test(uint256,uint256): 10, 5 -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -23,9 +23,10 @@ contract test {
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// getChoiceExp(uint256): 3 -> FAILURE # These should throw #
|
||||
// getChoiceFromSigned(int256): -1 -> FAILURE
|
||||
// getChoiceFromNegativeLiteral() -> FAILURE
|
||||
// getChoiceExp(uint256): 3 -> FAILURE, hex"4e487b71", 33 # These should throw #
|
||||
// getChoiceFromSigned(int256): -1 -> FAILURE, hex"4e487b71", 33
|
||||
// getChoiceFromNegativeLiteral() -> FAILURE, hex"4e487b71", 33
|
||||
// getChoiceExp(uint256): 2 -> 2 # These should work #
|
||||
// getChoiceExp(uint256): 0 -> 0
|
||||
|
@ -0,0 +1,32 @@
|
||||
contract test {
|
||||
enum ActionChoices {GoLeft, GoRight, GoStraight}
|
||||
|
||||
constructor() {}
|
||||
|
||||
function getChoiceExp(uint256 x) public returns (uint256 d) {
|
||||
choice = ActionChoices(x);
|
||||
d = uint256(choice);
|
||||
}
|
||||
|
||||
function getChoiceFromSigned(int256 x) public returns (uint256 d) {
|
||||
choice = ActionChoices(x);
|
||||
d = uint256(choice);
|
||||
}
|
||||
|
||||
function getChoiceFromNegativeLiteral() public returns (uint256 d) {
|
||||
choice = ActionChoices(-1);
|
||||
d = uint256(choice);
|
||||
}
|
||||
|
||||
ActionChoices choice;
|
||||
}
|
||||
|
||||
// ====
|
||||
// EVMVersion: <byzantium
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// getChoiceExp(uint256): 3 -> FAILURE # These should throw #
|
||||
// getChoiceFromSigned(int256): -1 -> FAILURE
|
||||
// getChoiceFromNegativeLiteral() -> FAILURE
|
||||
// getChoiceExp(uint256): 2 -> 2 # These should work #
|
||||
// getChoiceExp(uint256): 0 -> 0
|
@ -14,5 +14,5 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// intern() -> FAILURE # This should throw exceptions #
|
||||
// intern() -> FAILURE, hex"4e487b71", 0x51 # This should throw exceptions #
|
||||
// extern() -> FAILURE
|
||||
|
@ -17,4 +17,4 @@ contract C {
|
||||
}
|
||||
|
||||
// ----
|
||||
// t() -> FAILURE
|
||||
// t() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -18,4 +18,4 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// t() -> FAILURE
|
||||
// t() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -22,17 +22,17 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// EVMVersion: >=byzantium
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// get() -> 0x00
|
||||
// assert0_delegated() -> 0x01, 0x40, 0x0
|
||||
// get_delegated() -> 0x01, 0x40, 0x20, 0x0
|
||||
// set(uint256): 0x01 ->
|
||||
// get() -> 0x01
|
||||
// assert0_delegated() -> 0x00, 0x40, 0x0
|
||||
// assert0_delegated() -> 0x00, 0x40, 0x24, 0x4e487b7100000000000000000000000000000000000000000000000000000000, 0x0100000000000000000000000000000000000000000000000000000000
|
||||
// get_delegated() -> 0x01, 0x40, 0x20, 0x1
|
||||
// set(uint256): 0x2a ->
|
||||
// get() -> 0x2a
|
||||
// assert0_delegated() -> 0x00, 0x40, 0x0
|
||||
// assert0_delegated() -> 0x00, 0x40, 0x24, 0x4e487b7100000000000000000000000000000000000000000000000000000000, 0x0100000000000000000000000000000000000000000000000000000000
|
||||
// get_delegated() -> 0x01, 0x40, 0x20, 0x2a
|
||||
|
@ -8,4 +8,4 @@ contract test {
|
||||
// ----
|
||||
// f() ->
|
||||
// g() -> FAILURE
|
||||
// h() -> FAILURE
|
||||
// h() -> FAILURE, hex"4e487b71", 0x01
|
||||
|
@ -13,4 +13,4 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> FAILURE
|
||||
// test() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -24,4 +24,4 @@ contract C {
|
||||
// set() -> 7
|
||||
// ca() -> 7
|
||||
// d() -> 1
|
||||
// ca() -> FAILURE
|
||||
// ca() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -8,4 +8,4 @@ contract Test {
|
||||
}
|
||||
|
||||
// ----
|
||||
// f() -> FAILURE
|
||||
// f() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -16,6 +16,6 @@ contract C {
|
||||
|
||||
// ----
|
||||
// g() -> 2
|
||||
// h() -> FAILURE
|
||||
// h() -> FAILURE, hex"4e487b71", 0x51
|
||||
// set() ->
|
||||
// h() -> 2
|
||||
|
@ -51,6 +51,6 @@ contract C {
|
||||
// j(uint256): 1 -> 1
|
||||
// j(uint256): 2 -> 4
|
||||
// j(uint256): 4 -> 16
|
||||
// k(uint256): 1 -> FAILURE
|
||||
// k(uint256): 2 -> FAILURE
|
||||
// k(uint256): 4 -> FAILURE
|
||||
// k(uint256): 1 -> FAILURE, hex"4e487b71", 0x01
|
||||
// k(uint256): 2 -> FAILURE, hex"4e487b71", 0x01
|
||||
// k(uint256): 4 -> FAILURE, hex"4e487b71", 0x01
|
||||
|
@ -17,8 +17,8 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> FAILURE
|
||||
// g(bool): false -> FAILURE
|
||||
// f() -> FAILURE, hex"4e487b71", 0x01
|
||||
// g(bool): false -> FAILURE, hex"4e487b71", 0x01
|
||||
// g(bool): true -> true
|
||||
// h(bool): false -> FAILURE
|
||||
// h(bool): true -> true
|
||||
|
@ -16,6 +16,7 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=byzantium
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> FAILURE # should throw #
|
||||
// test() -> FAILURE, hex"4e487b71", 33 # should throw #
|
||||
|
@ -26,7 +26,8 @@ contract C {
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// test_return() -> FAILURE # both should throw #
|
||||
// test_inline_assignment() -> FAILURE
|
||||
// test_assignment() -> FAILURE
|
||||
// test_return() -> FAILURE, hex"4e487b71", 33 # both should throw #
|
||||
// test_inline_assignment() -> FAILURE, hex"4e487b71", 33
|
||||
// test_assignment() -> FAILURE, hex"4e487b71", 33
|
||||
|
@ -24,7 +24,8 @@ contract C {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// test_eq_ok() -> 1
|
||||
// test_eq() -> FAILURE # both should throw #
|
||||
// test_neq() -> FAILURE
|
||||
// test_eq() -> FAILURE, hex"4e487b71", 33 # both should throw #
|
||||
// test_neq() -> FAILURE, hex"4e487b71", 33
|
||||
|
@ -16,8 +16,9 @@ contract C {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// test_store_ok() -> 1
|
||||
// x() -> 0
|
||||
// test_store() -> FAILURE # should throw #
|
||||
// test_store() -> FAILURE, hex"4e487b71", 33 # should throw #
|
||||
|
@ -14,12 +14,12 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// EVMVersion: >homestead
|
||||
// allowNonExistingFunctions: true
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// _() -> FAILURE
|
||||
// e() -> FAILURE, hex"08c379a0", 0x20, 19, "Transaction failed."
|
||||
// f(bool): false -> FAILURE, hex"08c379a0", 0x20, 0
|
||||
// g(bool): false -> FAILURE, hex"08c379a0", 0x20, 15, "Value is false."
|
||||
// h() -> FAILURE
|
||||
// e() -> FAILURE, hex"08c379a0", 0x20, 0x13, "Transaction failed."
|
||||
// f(bool): false -> FAILURE, hex"08c379a0", 0x20, 0x00
|
||||
// g(bool): false -> FAILURE, hex"08c379a0", 0x20, 0x0f, "Value is false."
|
||||
// h() -> FAILURE, hex"4e487b71", 0x01
|
||||
|
@ -9,22 +9,24 @@ contract test {
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// EVMVersion: >=byzantium
|
||||
// ABIEncoderV1Only: true
|
||||
// compileViaYul: false
|
||||
// ----
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0
|
||||
// get(uint8): 0x02 -> 0
|
||||
// get(uint8): 0x03 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0x03 -> FAILURE, hex"4e487b71", 33
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x00, 0xef ->
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x01, 0x05 ->
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0x05
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
|
@ -10,31 +10,32 @@ contract test {
|
||||
}
|
||||
// ====
|
||||
// ABIEncoderV1Only: true
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// table(uint8): 0 -> 0
|
||||
// table(uint8): 0x01 -> 0
|
||||
// table(uint8): 0xa7 -> 0
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||
// table(uint8): 0 -> 0
|
||||
// table(uint8): 0x01 -> 0xa1
|
||||
// table(uint8): 0xa7 -> 0
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x00, 0xef ->
|
||||
// table(uint8): 0 -> 0xef
|
||||
// table(uint8): 0x01 -> 0xa1
|
||||
// table(uint8): 0xa7 -> 0
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x01, 0x05 ->
|
||||
// table(uint8): 0 -> 0xef
|
||||
// table(uint8): 0x01 -> 0x05
|
||||
// table(uint8): 0xa7 -> 0
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0x05
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
|
@ -16,20 +16,23 @@ contract test {
|
||||
L.set(table, k, v);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=byzantium
|
||||
// ABIEncoderV1Only: true
|
||||
// ----
|
||||
// library: L
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x00, 0xef ->
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
// set(uint8,uint8): 0x01, 0x05 ->
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0x05
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE, hex"4e487b71", 33
|
||||
|
@ -0,0 +1,39 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
enum E { A, B, C }
|
||||
library L {
|
||||
function get(mapping(E => uint8) storage table, E k) external returns (uint8) {
|
||||
return table[k];
|
||||
}
|
||||
function set(mapping(E => uint8) storage table, E k, uint8 v) external {
|
||||
table[k] = v;
|
||||
}
|
||||
}
|
||||
contract test {
|
||||
mapping(E => uint8) table;
|
||||
function get(E k) public returns (uint8 v) {
|
||||
return L.get(table, k);
|
||||
}
|
||||
function set(E k, uint8 v) public {
|
||||
L.set(table, k, v);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// library: L
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// set(uint8,uint8): 0x00, 0xef ->
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// set(uint8,uint8): 0x01, 0x05 ->
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0x05
|
||||
// get(uint8): 0xa7 -> FAILURE
|
32
test/libsolidity/semanticTests/types/mapping_enum_key_v2.sol
Normal file
32
test/libsolidity/semanticTests/types/mapping_enum_key_v2.sol
Normal file
@ -0,0 +1,32 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
enum E { A, B, C }
|
||||
contract test {
|
||||
mapping(E => uint8) table;
|
||||
function get(E k) public returns (uint8 v) {
|
||||
return table[k];
|
||||
}
|
||||
function set(E k, uint8 v) public {
|
||||
table[k] = v;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0
|
||||
// get(uint8): 0x02 -> 0
|
||||
// get(uint8): 0x03 -> FAILURE
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||
// get(uint8): 0 -> 0
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// set(uint8,uint8): 0x00, 0xef ->
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0xa1
|
||||
// get(uint8): 0xa7 -> FAILURE
|
||||
// set(uint8,uint8): 0x01, 0x05 ->
|
||||
// get(uint8): 0 -> 0xef
|
||||
// get(uint8): 0x01 -> 0x05
|
||||
// get(uint8): 0xa7 -> FAILURE
|
@ -20,4 +20,4 @@ contract Test {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> FAILURE
|
||||
// f() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -20,4 +20,4 @@ contract Test {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> FAILURE
|
||||
// f() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -36,4 +36,4 @@ contract InvalidTest {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// run() -> FAILURE
|
||||
// run() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -15,5 +15,5 @@ contract InvalidTest {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> FAILURE
|
||||
// f() -> FAILURE
|
||||
// f() -> FAILURE, hex"4e487b71", 0x51
|
||||
// f() -> FAILURE, hex"4e487b71", 0x51
|
||||
|
@ -20,5 +20,5 @@ contract C {
|
||||
// ----
|
||||
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 0, 0, 32, "01234567890123456789012345678901" -> 0
|
||||
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 1, 3, 32, "01234567890123456789012345678901" -> 0
|
||||
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 3, 3, 32, "01234567890123456789012345678901" -> FAILURE
|
||||
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 1, 5, 32, "01234567890123456789012345678901" -> FAILURE
|
||||
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 3, 3, 32, "01234567890123456789012345678901" -> FAILURE, hex"4e487b71", 0x32
|
||||
// set(string,uint256,uint256,uint256,uint256): 0xa0, 2, 4, 1, 5, 32, "01234567890123456789012345678901" -> FAILURE, hex"4e487b71", 0x32
|
||||
|
@ -18,5 +18,5 @@ contract C {
|
||||
// ----
|
||||
// set(string,uint256,uint256): 0x60, 2, 0, 32, "01234567890123456789012345678901" -> 0
|
||||
// set(string,uint256,uint256): 0x60, 2, 1, 32, "01234567890123456789012345678901" -> 0
|
||||
// set(string,uint256,uint256): 0x60, 2, 2, 32, "01234567890123456789012345678901" -> FAILURE
|
||||
// set(string,uint256,uint256): 0x60, 2, 2, 32, "01234567890123456789012345678901" -> FAILURE, hex"4e487b71", 0x32
|
||||
// set(string,uint256,uint256): 0x60, 200, 199, 32, "01234567890123456789012345678901" -> 0
|
||||
|
@ -19,4 +19,4 @@ contract C {
|
||||
// set(string,uint256,uint256): 0x60, 5, 0, 32, "01234567890123456789012345678901" -> 0
|
||||
// set(string,uint256,uint256): 0x60, 5, 1, 32, "01234567890123456789012345678901" -> 0
|
||||
// set(string,uint256,uint256): 0x60, 5, 4, 32, "01234567890123456789012345678901" -> 0
|
||||
// set(string,uint256,uint256): 0x60, 5, 5, 32, "01234567890123456789012345678901" -> FAILURE
|
||||
// set(string,uint256,uint256): 0x60, 5, 5, 32, "01234567890123456789012345678901" -> FAILURE, hex"4e487b71", 0x32
|
||||
|
@ -20,7 +20,7 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// test(uint256,uint256): 0,0 -> FAILURE
|
||||
// test(uint256,uint256): 1,0 -> 1
|
||||
// test(uint256,uint256): 10,5 -> 6
|
||||
// test(uint256,uint256): 10,50 -> FAILURE
|
||||
// test(uint256,uint256): 0, 0 -> FAILURE, hex"4e487b71", 0x32
|
||||
// test(uint256,uint256): 1, 0 -> 1
|
||||
// test(uint256,uint256): 10, 5 -> 6
|
||||
// test(uint256,uint256): 10, 50 -> FAILURE, hex"4e487b71", 0x32
|
||||
|
@ -28,8 +28,8 @@ contract C {
|
||||
// index(uint256): 10 -> true
|
||||
// index(uint256): 20 -> true
|
||||
// index(uint256): 0xFF -> true
|
||||
// accessIndex(uint256,int256): 10,1 -> 2
|
||||
// accessIndex(uint256,int256): 10,0 -> 1
|
||||
// accessIndex(uint256,int256): 10,11 -> FAILURE
|
||||
// accessIndex(uint256,int256): 10,10 -> FAILURE
|
||||
// accessIndex(uint256,int256): 10,-1 -> FAILURE
|
||||
// accessIndex(uint256,int256): 10, 1 -> 2
|
||||
// accessIndex(uint256,int256): 10, 0 -> 1
|
||||
// accessIndex(uint256,int256): 10, 11 -> FAILURE, hex"4e487b71", 0x32
|
||||
// accessIndex(uint256,int256): 10, 10 -> FAILURE, hex"4e487b71", 0x32
|
||||
// accessIndex(uint256,int256): 10, -1 -> FAILURE, hex"4e487b71", 0x32
|
||||
|
@ -17,9 +17,9 @@ contract C {
|
||||
// test(uint256): 42 ->
|
||||
// getLength() -> 1
|
||||
// fetch(uint256): 0 -> 42
|
||||
// fetch(uint256): 1 -> FAILURE
|
||||
// fetch(uint256): 1 -> FAILURE, hex"4e487b71", 0x32
|
||||
// test(uint256): 23 ->
|
||||
// getLength() -> 2
|
||||
// fetch(uint256): 0 -> 42
|
||||
// fetch(uint256): 1 -> 23
|
||||
// fetch(uint256): 2 -> FAILURE
|
||||
// fetch(uint256): 2 -> FAILURE, hex"4e487b71", 0x32
|
||||
|
@ -17,9 +17,9 @@ contract C {
|
||||
// test(uint256): 42 ->
|
||||
// getLength() -> 1
|
||||
// fetch(uint256): 0 -> 42
|
||||
// fetch(uint256): 1 -> FAILURE
|
||||
// fetch(uint256): 1 -> FAILURE, hex"4e487b71", 0x32
|
||||
// test(uint256): 23 ->
|
||||
// getLength() -> 2
|
||||
// fetch(uint256): 0 -> 42
|
||||
// fetch(uint256): 1 -> 23
|
||||
// fetch(uint256): 2 -> FAILURE
|
||||
// fetch(uint256): 2 -> FAILURE, hex"4e487b71", 0x32
|
||||
|
@ -12,12 +12,12 @@ contract C {
|
||||
// ====
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// test_boundary_check(uint256, uint256): 10, 11 -> FAILURE
|
||||
// test_boundary_check(uint256, uint256): 10, 9 -> 0
|
||||
// test_boundary_check(uint256, uint256): 1, 9 -> FAILURE
|
||||
// test_boundary_check(uint256, uint256): 1, 1 -> FAILURE
|
||||
// test_boundary_check(uint256, uint256): 10, 10 -> FAILURE
|
||||
// test_boundary_check(uint256, uint256): 256, 256 -> FAILURE
|
||||
// test_boundary_check(uint256, uint256): 256, 255 -> 0
|
||||
// test_boundary_check(uint256, uint256): 256, 0xFFFF -> FAILURE
|
||||
// test_boundary_check(uint256, uint256): 256, 2 -> 0
|
||||
// test_boundary_check(uint256,uint256): 10, 11 -> FAILURE, hex"4e487b71", 0x32
|
||||
// test_boundary_check(uint256,uint256): 10, 9 -> 0
|
||||
// test_boundary_check(uint256,uint256): 1, 9 -> FAILURE, hex"4e487b71", 0x32
|
||||
// test_boundary_check(uint256,uint256): 1, 1 -> FAILURE, hex"4e487b71", 0x32
|
||||
// test_boundary_check(uint256,uint256): 10, 10 -> FAILURE, hex"4e487b71", 0x32
|
||||
// test_boundary_check(uint256,uint256): 256, 256 -> FAILURE, hex"4e487b71", 0x32
|
||||
// test_boundary_check(uint256,uint256): 256, 255 -> 0
|
||||
// test_boundary_check(uint256,uint256): 256, 0xFFFF -> FAILURE, hex"4e487b71", 0x32
|
||||
// test_boundary_check(uint256,uint256): 256, 2 -> 0
|
||||
|
@ -8,4 +8,4 @@ contract C {
|
||||
// EVMVersion: >=petersburg
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// popEmpty() -> FAILURE
|
||||
// popEmpty() -> FAILURE, hex"4e487b71", 0x31
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user