diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | docs/assembly.rst | 2 | ||||
-rw-r--r-- | docs/contracts.rst | 2 | ||||
-rw-r--r-- | docs/types.rst | 8 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 2 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.cpp | 5 | ||||
-rw-r--r-- | test/compilationTests/stringutils/strings.sol | 18 | ||||
-rw-r--r-- | test/libsolidity/InlineAssembly.cpp | 6 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 59 |
9 files changed, 57 insertions, 46 deletions
diff --git a/Changelog.md b/Changelog.md index c1077926..6877ae22 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ Breaking Changes: * General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code. * Type Checker: Disallow arithmetic operations for Boolean variables. * Disallow trailing dots that are not followed by a number. + * Remove assembly instructions ``sha3`` and ``suicide`` Language Features: * General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions. diff --git a/docs/assembly.rst b/docs/assembly.rst index f7b721ab..edc826ac 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -220,8 +220,6 @@ In the grammar, opcodes are represented as pre-defined identifiers. +-------------------------+-----+---+-----------------------------------------------------------------+ | keccak256(p, n) | | F | keccak(mem[p...(p+n))) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| sha3(p, n) | | F | keccak(mem[p...(p+n))) | -+-------------------------+-----+---+-----------------------------------------------------------------+ | jump(label) | `-` | F | jump to label / code position | +-------------------------+-----+---+-----------------------------------------------------------------+ | jumpi(label, cond) | `-` | F | jump to label if cond is nonzero | diff --git a/docs/contracts.rst b/docs/contracts.rst index 3d6ee869..e4f49f43 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -774,7 +774,7 @@ The use in the JavaScript API would be as follows: // watch for changes event.watch(function(error, result){ // result will contain various information - // including the argumets given to the `Deposit` + // including the arguments given to the `Deposit` // call. if (!error) console.log(result); diff --git a/docs/types.rst b/docs/types.rst index b3631f74..08b74241 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -226,10 +226,6 @@ Dynamically-sized byte array ``string``: Dynamically-sized UTF-8-encoded string, see :ref:`arrays`. Not a value-type! -As a rule of thumb, use ``bytes`` for arbitrary-length raw byte data and ``string`` -for arbitrary-length string (UTF-8) data. If you can limit the length to a certain -number of bytes, always use one of ``bytes1`` to ``bytes32`` because they are much cheaper. - .. index:: address, literal;address .. _address_literals: @@ -602,8 +598,10 @@ shaves off one level in the type from the right). Variables of type ``bytes`` and ``string`` are special arrays. A ``bytes`` is similar to ``byte[]``, but it is packed tightly in calldata. ``string`` is equal to ``bytes`` but does not allow length or index access (for now). - So ``bytes`` should always be preferred over ``byte[]`` because it is cheaper. +As a rule of thumb, use ``bytes`` for arbitrary-length raw byte data and ``string`` +for arbitrary-length string (UTF-8) data. If you can limit the length to a certain +number of bytes, always use one of ``bytes1`` to ``bytes32`` because they are much cheaper. .. note:: If you want to access the byte-representation of a string ``s``, use diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 7f5ec46a..eb56e8ae 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2529,6 +2529,7 @@ string FunctionType::richIdentifier() const case Kind::AddMod: id += "addmod"; break; case Kind::MulMod: id += "mulmod"; break; case Kind::ArrayPush: id += "arraypush"; break; + case Kind::ArrayPop: id += "arraypop"; break; case Kind::ByteArrayPush: id += "bytearraypush"; break; case Kind::ObjectCreation: id += "objectcreation"; break; case Kind::Assert: id += "assert"; break; @@ -2683,6 +2684,7 @@ unsigned FunctionType::sizeOnStack() const case Kind::BareDelegateCall: case Kind::Internal: case Kind::ArrayPush: + case Kind::ArrayPop: case Kind::ByteArrayPush: size = 1; break; diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index d300f8fb..431f33e5 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -318,11 +318,6 @@ std::map<string, dev::solidity::Instruction> const& Parser::instructions() transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); }); s_instructions[name] = instruction.second; } - - // add alias for suicide - s_instructions["suicide"] = solidity::Instruction::SELFDESTRUCT; - // add alis for sha3 - s_instructions["sha3"] = solidity::Instruction::KECCAK256; } return s_instructions; } diff --git a/test/compilationTests/stringutils/strings.sol b/test/compilationTests/stringutils/strings.sol index 0a2d68bd..771f7a53 100644 --- a/test/compilationTests/stringutils/strings.sol +++ b/test/compilationTests/stringutils/strings.sol @@ -339,7 +339,7 @@ library strings { */ function keccak(slice self) internal returns (bytes32 ret) { assembly { - ret := sha3(mload(add(self, 32)), mload(self)) + ret := keccak256(mload(add(self, 32)), mload(self)) } } @@ -363,7 +363,7 @@ library strings { let len := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) - equal := eq(sha3(selfptr, len), sha3(needleptr, len)) + equal := eq(keccak256(selfptr, len), keccak256(needleptr, len)) } return equal; } @@ -386,7 +386,7 @@ library strings { let len := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) - equal := eq(sha3(selfptr, len), sha3(needleptr, len)) + equal := eq(keccak256(selfptr, len), keccak256(needleptr, len)) } } @@ -419,7 +419,7 @@ library strings { assembly { let len := mload(needle) let needleptr := mload(add(needle, 0x20)) - equal := eq(sha3(selfptr, len), sha3(needleptr, len)) + equal := eq(keccak256(selfptr, len), keccak256(needleptr, len)) } return equal; @@ -443,7 +443,7 @@ library strings { assembly { let len := mload(needle) let needleptr := mload(add(needle, 0x20)) - equal := eq(sha3(selfptr, len), sha3(needleptr, len)) + equal := eq(keccak256(selfptr, len), keccak256(needleptr, len)) } } @@ -479,11 +479,11 @@ library strings { } else { // For long needles, use hashing bytes32 hash; - assembly { hash := sha3(needleptr, needlelen) } + assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr; for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; - assembly { testHash := sha3(ptr, needlelen) } + assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; @@ -519,11 +519,11 @@ library strings { } else { // For long needles, use hashing bytes32 hash; - assembly { hash := sha3(needleptr, needlelen) } + assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr + (selflen - needlelen); while (ptr >= selfptr) { bytes32 testHash; - assembly { testHash := sha3(ptr, needlelen) } + assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr + needlelen; ptr -= 1; diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 181ca959..3046372f 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -178,9 +178,9 @@ BOOST_AUTO_TEST_CASE(simple_instructions) BOOST_CHECK(successParse("{ dup1 dup1 mul dup1 sub pop }")); } -BOOST_AUTO_TEST_CASE(suicide_selfdestruct) +BOOST_AUTO_TEST_CASE(selfdestruct) { - BOOST_CHECK(successParse("{ 0x01 suicide 0x02 selfdestruct }")); + BOOST_CHECK(successParse("{ 0x02 selfdestruct }")); } BOOST_AUTO_TEST_CASE(keywords) @@ -740,8 +740,6 @@ BOOST_AUTO_TEST_CASE(keccak256) { BOOST_CHECK(successAssemble("{ 0 0 keccak256 pop }")); BOOST_CHECK(successAssemble("{ pop(keccak256(0, 0)) }")); - BOOST_CHECK(successAssemble("{ 0 0 sha3 pop }")); - BOOST_CHECK(successAssemble("{ pop(sha3(0, 0)) }")); } BOOST_AUTO_TEST_CASE(returndatasize) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index f1fac396..b53a9294 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -5397,6 +5397,40 @@ BOOST_AUTO_TEST_CASE(byte_array_pop_copy_long) )); } +BOOST_AUTO_TEST_CASE(array_pop_isolated) +{ + char const* sourceCode = R"( + // This tests that the compiler knows the correct size of the function on the stack. + contract c { + uint[] data; + function test() public returns (uint x) { + x = 2; + data.pop; + x = 3; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(3)); +} + +BOOST_AUTO_TEST_CASE(byte_array_pop_isolated) +{ + char const* sourceCode = R"( + // This tests that the compiler knows the correct size of the function on the stack. + contract c { + bytes data; + function test() public returns (uint x) { + x = 2; + data.pop; + x = 3; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(3)); +} + BOOST_AUTO_TEST_CASE(external_array_args) { char const* sourceCode = R"( @@ -8585,15 +8619,15 @@ BOOST_AUTO_TEST_CASE(inline_array_return) { char const* sourceCode = R"( contract C { - uint8[] tester; + uint8[] tester; function f() returns (uint8[5]) { return ([1,2,3,4,5]); } function test() returns (uint8, uint8, uint8, uint8, uint8) { - tester = f(); + tester = f(); return (tester[0], tester[1], tester[2], tester[3], tester[4]); } - + } )"; compileAndRun(sourceCode, 0, "C"); @@ -8617,13 +8651,13 @@ BOOST_AUTO_TEST_CASE(inline_array_singleton) BOOST_AUTO_TEST_CASE(inline_long_string_return) { char const* sourceCode = R"( - contract C { + contract C { function f() returns (string) { return (["somethingShort", "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"][1]); } } )"; - + string strLong = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), encodeDyn(strLong)); @@ -11431,26 +11465,11 @@ BOOST_AUTO_TEST_CASE(keccak256_assembly) =: ret } } - function h() pure returns (bytes32 ret) { - assembly { - ret := sha3(0, 0) - } - } - function i() pure returns (bytes32 ret) { - assembly { - 0 - 0 - sha3 - =: ret - } - } } )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); ABI_CHECK(callContractFunction("g()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - ABI_CHECK(callContractFunction("h()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - ABI_CHECK(callContractFunction("i()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); } BOOST_AUTO_TEST_CASE(multi_modifiers) |