aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--docs/contributing.rst4
-rw-r--r--docs/control-structures.rst22
-rw-r--r--docs/introduction-to-smart-contracts.rst10
-rw-r--r--docs/miscellaneous.rst22
-rw-r--r--liblll/CompilerState.cpp10
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp2
-rw-r--r--libsolidity/ast/Types.cpp6
-rw-r--r--libsolidity/formal/Why3Translator.cpp14
-rw-r--r--libsolidity/formal/Why3Translator.h1
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp4
-rwxr-xr-xscripts/isolateTests.py24
-rw-r--r--test/libsolidity/InlineAssembly.cpp5
-rw-r--r--test/libsolidity/SolidityExecutionFramework.h10
14 files changed, 107 insertions, 28 deletions
diff --git a/Changelog.md b/Changelog.md
index 1560990d..bc79b88a 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -9,6 +9,7 @@ Features:
Bugfixes:
* Disallow unknown options in `solc`
* Inline assembly: support the `address` opcode
+ * Inline assembly: fix parsing of assignment after a label.
### 0.4.2 (2016-09-17)
diff --git a/docs/contributing.rst b/docs/contributing.rst
index a316abd6..111fb932 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -15,7 +15,9 @@ In particular, we need help in the following areas:
<http://ethereum.stackexchange.com/>`_ and the `Solidity Gitter
<https://gitter.im/ethereum/solidity>`_
* Fixing and responding to `Solidity's GitHub issues
- <https://github.com/ethereum/solidity/issues>`_
+ <https://github.com/ethereum/solidity/issues>`_, especially those tagged as
+ `up-for-grabs <https://github.com/ethereum/solidity/issues?q=is%3Aopen+is%3Aissue+label%3Aup-for-grabs>`_ which are
+ meant as introductory issues for external contributors.
How to Report Issues
====================
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index db24d5c3..c754de64 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -322,14 +322,16 @@ In the following example, we show how ``throw`` can be used to easily revert an
}
}
-Currently, there are six situations, where exceptions happen automatically in Solidity:
+Currently, there are situations, where exceptions happen automatically in Solidity:
-1. If you access an array beyond its length (i.e. ``x[i]`` where ``i >= x.length``).
-2. If a function called via a message call does not finish properly (i.e. it runs out of gas or throws an exception itself).
-3. If a non-existent function on a library is called or Ether is sent to a library.
-4. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
-5. If you perform an external function call targeting a contract that contains no code.
-6. If a contract-creation call using the ``new`` keyword fails.
+1. If you access an array at a too large or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``).
+2. If you access a fixed-length ``bytesN`` at a too large or negative index.
+3. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall`` or ``callcode`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``.
+4. If you create a contract using the ``new`` keyword but the contract creation does not finish properly (see above for the definition of "not finish properly").
+5. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
+6. If you perform an external function call targeting a contract that contains no code.
+7. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function).
+8. If your contract receives Ether via a public accessor function.
Internally, Solidity performs an "invalid jump" when an exception is thrown and thus causes the EVM to revert all changes made to the state. The reason for this is that there is no safe way to continue execution, because an expected effect did not occur. Because we want to retain the atomicity of transactions, the safest thing to do is to revert all changes and make the whole transaction (or at least call) without effect.
@@ -503,7 +505,7 @@ The opcodes ``pushi`` and ``jumpdest`` cannot be used directly.
+-------------------------+------+-----------------------------------------------------------------+
| pc | | current position in code |
+-------------------------+------+-----------------------------------------------------------------+
-| pop | `*` | remove topmost stack slot |
+| pop(x) | `-` | remove the element pushed by x |
+-------------------------+------+-----------------------------------------------------------------+
| dup1 ... dup16 | | copy ith stack slot to the top (counting from top) |
+-------------------------+------+-----------------------------------------------------------------+
@@ -559,9 +561,9 @@ The opcodes ``pushi`` and ``jumpdest`` cannot be used directly.
| delegatecall(g, a, in, | | identical to `callcode` but also keep ``caller`` |
| insize, out, outsize) | | and ``callvalue`` |
+-------------------------+------+-----------------------------------------------------------------+
-| return(p, s) | `*` | end execution, return data mem[p..(p+s)) |
+| return(p, s) | `-` | end execution, return data mem[p..(p+s)) |
+-------------------------+------+-----------------------------------------------------------------+
-| selfdestruct(a) | `*` | end execution, destroy current contract and send funds to a |
+| selfdestruct(a) | `-` | end execution, destroy current contract and send funds to a |
+-------------------------+------+-----------------------------------------------------------------+
| log0(p, s) | `-` | log without topics and data mem[p..(p+s)) |
+-------------------------+------+-----------------------------------------------------------------+
diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst
index 922056ec..ad0a9650 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -348,10 +348,12 @@ storage. A contract can neither read nor write to any storage apart
from its own.
The second memory area is called **memory**, of which a contract obtains
-a freshly cleared instance for each message call. Memory can be
-addressed at byte level, but read and written to in 32 byte (256-bit)
-chunks. Memory is more costly the larger it grows (it scales
-quadratically).
+a freshly cleared instance for each message call. Memory is linear and can be
+addressed at byte level, but reads are limited to a width of 256 bits, while writes
+can be either 8 bits or 256 bits wide. Memory is expanded by a word (256-bit), when
+accessing (either reading or writing) a previously untouched memory word (ie. any offset
+within a word). At the time of expansion, the cost in gas must be paid. Memory is more
+costly the larger it grows (it scales quadratically).
The EVM is not a register machine but a stack machine, so all
computations are performed on an area called the **stack**. It has a maximum size of
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index c4a954ad..72e32617 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -56,6 +56,23 @@ So for the following contract snippet::
The position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``.
+****************
+Layout in Memory
+****************
+
+Solidity reserves three 256-bit slots:
+- 0 - 64: scratch space for hashing methods
+- 64 - 96: currently allocated memory size (aka. free memory pointer)
+
+Scratch space can be used between statements (ie. within inline assembly).
+
+Solidity always places new objects at the free memory pointer and memory is never freed (this might change in the future).
+
+.. warning::
+ There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifecycle, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one shouldn't expect the free memory to be zeroed out.
+
+.. index: memory layout
+
*****************
Esoteric Features
*****************
@@ -347,3 +364,8 @@ These keywords are reserved in Solidity. They might become part of the syntax in
``abstract``, ``after``, ``case``, ``catch``, ``final``, ``in``, ``inline``, ``interface``, ``let``, ``match``,
``of``, ``pure``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``, ``view``.
+
+Language Grammar
+================
+
+The entire language grammar is `available here <https://github.com/ethereum/solidity/blob/release/libsolidity/grammar.txt>`_.
diff --git a/liblll/CompilerState.cpp b/liblll/CompilerState.cpp
index 63351bc4..1d83192c 100644
--- a/liblll/CompilerState.cpp
+++ b/liblll/CompilerState.cpp
@@ -45,8 +45,6 @@ CodeFragment const& CompilerState::getDef(std::string const& _s)
void CompilerState::populateStandard()
{
static const string s = "{"
- "(def 'gav 0x51ba59315b3a95761d0863b05ccc7a7f54703d99)"
- "(def 'config 0x661005d2720d855f1d9976f88bb10c1a3398c77f)"
"(def 'allgas (- (gas) 21))"
"(def 'send (to value) (call allgas to value 0 0 0 0))"
"(def 'send (gaslimit to value) (call gaslimit to value 0 0 0 0))"
@@ -60,18 +58,12 @@ void CompilerState::populateStandard()
"(def 'sha3 (val) { [0]:val (sha3 0 32) })"
"(def 'sha3pair (a b) { [0]:a [32]:b (sha3 0 64) })"
"(def 'sha3trip (a b c) { [0]:a [32]:b [64]:c (sha3 0 96) })"
+ "(def 'keccak256 (loc len) (sha3 loc len))"
"(def 'return (val) { [0]:val (return 0 32) })"
"(def 'returnlll (code) (return 0 (lll code 0)) )"
"(def 'makeperm (name pos) { (def name (sload pos)) (def name (v) (sstore pos v)) } )"
"(def 'permcount 0)"
"(def 'perm (name) { (makeperm name permcount) (def 'permcount (+ permcount 1)) } )"
- "(def 'namereg (msg config 0))"
- "(def 'coinreg (msg config 1))"
- "(def 'gavcoin (msg config 2))"
- "(def 'sendgavcoin (to value) { [32]'send [64]:to [96]:value (call allgas gavcoin 0 32 96 0 0) })"
- "(def 'regname (name) { [32]'register [64]name (call allgas namereg 0 32 64 0 0) })"
- "(def 'regcoin (name) { [32]name (call allgas coinreg 0 32 32 0 0) })"
- "(def 'regcoin (name denom) { [32]name [64]denom (call allgas coinreg 0 32 64 0 0) })"
"(def 'ecrecover (r s v hash) { [0] r [32] s [64] v [96] hash (msg allgas 1 0 0 128) })"
"(def 'sha256 (data datasize) (msg allgas 2 0 data datasize))"
"(def 'ripemd160 (data datasize) (msg allgas 3 0 data datasize))"
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp
index a95b4879..dc8c1806 100644
--- a/libsolidity/analysis/SyntaxChecker.cpp
+++ b/libsolidity/analysis/SyntaxChecker.cpp
@@ -67,7 +67,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
{
solAssert(!_pragma.tokens().empty(), "");
solAssert(_pragma.tokens().size() == _pragma.literals().size(), "");
- if (_pragma.tokens()[0] != Token::Identifier && _pragma.literals()[0] != "solidity")
+ if (_pragma.tokens()[0] != Token::Identifier || _pragma.literals()[0] != "solidity")
syntaxError(_pragma.location(), "Unknown pragma \"" + _pragma.literals()[0] + "\"");
else
{
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 6d1af534..edb0fbe4 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -574,7 +574,11 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
FixedBytesType const& fixedBytes = dynamic_cast<FixedBytesType const&>(_convertTo);
if (!isFractional())
- return fixedBytes.numBytes() * 8 >= integerType()->numBits();
+ {
+ if (integerType())
+ return fixedBytes.numBytes() * 8 >= integerType()->numBits();
+ return false;
+ }
else
return false;
}
diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp
index f3831b40..813fa3ab 100644
--- a/libsolidity/formal/Why3Translator.cpp
+++ b/libsolidity/formal/Why3Translator.cpp
@@ -757,6 +757,20 @@ bool Why3Translator::visit(Literal const& _literal)
return false;
}
+bool Why3Translator::visit(PragmaDirective const& _pragma)
+{
+ if (_pragma.tokens().empty())
+ error(_pragma, "Not supported");
+ else if (_pragma.literals().empty())
+ error(_pragma, "Not supported");
+ else if (_pragma.literals()[0] != "solidity")
+ error(_pragma, "Not supported");
+ else if (_pragma.tokens()[0] != Token::Identifier)
+ error(_pragma, "A literal 'solidity' is not an identifier. Strange");
+
+ return false;
+}
+
bool Why3Translator::isStateVariable(VariableDeclaration const* _var) const
{
return contains(m_currentContract.stateVariables, _var);
diff --git a/libsolidity/formal/Why3Translator.h b/libsolidity/formal/Why3Translator.h
index 22bfff89..4fdac385 100644
--- a/libsolidity/formal/Why3Translator.h
+++ b/libsolidity/formal/Why3Translator.h
@@ -94,6 +94,7 @@ private:
virtual bool visit(IndexAccess const& _node) override;
virtual bool visit(Identifier const& _node) override;
virtual bool visit(Literal const& _node) override;
+ virtual bool visit(PragmaDirective const& _node) override;
virtual bool visitNode(ASTNode const& _node) override
{
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index ee9c150e..8d2c2ed4 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -95,7 +95,9 @@ assembly::Statement Parser::parseStatement()
fatalParserError("Label name / variable name must precede \":\".");
assembly::Identifier const& identifier = boost::get<assembly::Identifier>(statement);
m_scanner->next();
- if (m_scanner->currentToken() == Token::Assign)
+ // identifier:=: should be parsed as identifier: =: (i.e. a label),
+ // while identifier:= (being followed by a non-colon) as identifier := (assignment).
+ if (m_scanner->currentToken() == Token::Assign && m_scanner->peekNextToken() != Token::Colon)
{
// functional assignment
FunctionalAssignment funAss = createWithLocation<FunctionalAssignment>(identifier.location);
diff --git a/scripts/isolateTests.py b/scripts/isolateTests.py
new file mode 100755
index 00000000..fed779d3
--- /dev/null
+++ b/scripts/isolateTests.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+#
+# This script reads C++ source files and writes all
+# multi-line strings into individual files.
+# This can be used to extract the Solidity test cases
+# into files for e.g. fuzz testing as
+# scripts/isolateTests.py tests/libsolidity/SolidityEndToEndTest.cpp
+
+import sys
+lines = sys.stdin.read().split('\n')
+inside = False
+tests = []
+for l in lines:
+ if inside:
+ if l.strip().endswith(')";'):
+ inside = False
+ else:
+ tests[-1] += l + '\n'
+ else:
+ if l.strip().endswith('R"('):
+ inside = True
+ tests += ['']
+for i in range(len(tests)):
+ open('test%d.sol' % i, 'w').write(tests[i])
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index 136d72e6..45eceb34 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -157,6 +157,11 @@ BOOST_AUTO_TEST_CASE(oversize_string_literals)
BOOST_CHECK(!successAssemble("{ let x := \"123456789012345678901234567890123\" }"));
}
+BOOST_AUTO_TEST_CASE(assignment_after_tag)
+{
+ BOOST_CHECK(successParse("{ let x := 1 { tag: =: x } }"));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h
index 1cd45603..7d44edaf 100644
--- a/test/libsolidity/SolidityExecutionFramework.h
+++ b/test/libsolidity/SolidityExecutionFramework.h
@@ -39,6 +39,7 @@ namespace dev
{
namespace solidity
{
+ using rational = boost::rational<dev::bigint>;
/// An Ethereum address: 20 bytes.
/// @NOTE This is not endian-specific; it's just a bunch of bytes.
using Address = h160;
@@ -155,6 +156,14 @@ public:
static bytes encode(char const* _value) { return encode(std::string(_value)); }
static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; }
static bytes encode(u256 const& _value) { return toBigEndian(_value); }
+ /// @returns the fixed-point encoding of a rational number with a given
+ /// number of fractional bits.
+ static bytes encode(std::pair<rational, int> const& _valueAndPrecision)
+ {
+ rational const& value = _valueAndPrecision.first;
+ int fractionalBits = _valueAndPrecision.second;
+ return encode(u256((value.numerator() << fractionalBits) / value.denominator()));
+ }
static bytes encode(h256 const& _value) { return _value.asBytes(); }
static bytes encode(bytes const& _value, bool _padLeft = true)
{
@@ -186,7 +195,6 @@ public:
{
return encodeArgs(u256(0x20), u256(_arg.size()), _arg);
}
-
class ContractInterface
{
public: