aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsubtly <subtly>2015-07-05 15:48:22 +0800
committersubtly <subtly>2015-07-05 15:48:22 +0800
commit5ca31adda6ad8b6391a463cb48476a63a195c9b7 (patch)
treeb6d7098348915e3663cda20dc9c42d93b5af7bb2
parent235f17c67427ed23c98f74c5863f7e1722815cce (diff)
parenta393acd0b26d6c9cc2bd7c74730fdfb9d6fc9ed6 (diff)
downloaddexon-solidity-5ca31adda6ad8b6391a463cb48476a63a195c9b7.tar.gz
dexon-solidity-5ca31adda6ad8b6391a463cb48476a63a195c9b7.tar.zst
dexon-solidity-5ca31adda6ad8b6391a463cb48476a63a195c9b7.zip
Merge branch 'develop' into rlpx
-rw-r--r--CMakeLists.txt4
-rw-r--r--libsolidity/SolidityEndToEndTest.cpp265
-rw-r--r--libsolidity/SolidityNameAndTypeResolution.cpp97
-rw-r--r--libsolidity/SolidityWallet.cpp31
4 files changed, 384 insertions, 13 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d39a5cca..952b1674 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -74,7 +74,9 @@ target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(testeth ${CURL_LIBRARIES})
target_link_libraries(testeth ethereum)
target_link_libraries(testeth ethcore)
-target_link_libraries(testeth secp256k1)
+if (NOT WIN32)
+ target_link_libraries(testeth secp256k1)
+endif()
if (JSCONSOLE)
target_link_libraries(testeth jsengine)
diff --git a/libsolidity/SolidityEndToEndTest.cpp b/libsolidity/SolidityEndToEndTest.cpp
index a01e98cf..3ddb0552 100644
--- a/libsolidity/SolidityEndToEndTest.cpp
+++ b/libsolidity/SolidityEndToEndTest.cpp
@@ -4493,7 +4493,7 @@ BOOST_AUTO_TEST_CASE(bytes_in_constructors_packer)
}
}
contract Main is Base {
- function Main(bytes s, uint x) Base(x, s){}//f(s)) {}
+ function Main(bytes s, uint x) Base(x, f(s)) {}
function f(bytes s) returns (bytes) {
return s;
}
@@ -4517,6 +4517,45 @@ BOOST_AUTO_TEST_CASE(bytes_in_constructors_packer)
);
}
+BOOST_AUTO_TEST_CASE(arrays_in_constructors)
+{
+ char const* sourceCode = R"(
+ contract Base {
+ uint public m_x;
+ address[] m_s;
+ function Base(uint x, address[] s) {
+ m_x = x;
+ m_s = s;
+ }
+ function part(uint i) returns (address) {
+ return m_s[i];
+ }
+ }
+ contract Main is Base {
+ function Main(address[] s, uint x) Base(x, f(s)) {}
+ function f(address[] s) returns (address[]) {
+ return s;
+ }
+ }
+ contract Creator {
+ function f(uint x, address[] s) returns (uint r, address ch) {
+ var c = new Main(s, x);
+ r = c.m_x();
+ ch = c.part(x);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Creator");
+ vector<u256> s1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ bytes dyn1 = encodeArgs(u256(s1.size()), s1);
+ u256 x = 7;
+ bytes args1 = encodeArgs(x, u256(0x40)) + dyn1;
+ BOOST_REQUIRE(
+ callContractFunction("f(uint256,address[])", asString(args1)) ==
+ encodeArgs(x, s1[unsigned(x)])
+ );
+}
+
BOOST_AUTO_TEST_CASE(arrays_from_and_to_storage)
{
char const* sourceCode = R"(
@@ -4691,6 +4730,35 @@ BOOST_AUTO_TEST_CASE(memory_types_initialisation)
BOOST_CHECK(callContractFunction("nestedStat()") == encodeArgs(vector<u256>(3 * 7)));
}
+BOOST_AUTO_TEST_CASE(memory_arrays_delete)
+{
+ char const* sourceCode = R"(
+ contract Test {
+ function del() returns (uint24[3][4]) {
+ uint24[3][4] memory x;
+ for (uint24 i = 0; i < x.length; i ++)
+ for (uint24 j = 0; j < x[i].length; j ++)
+ x[i][j] = i * 0x10 + j;
+ delete x[1];
+ delete x[3][2];
+ return x;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Test");
+
+ vector<u256> data(3 * 4);
+ for (unsigned i = 0; i < 4; i++)
+ for (unsigned j = 0; j < 3; j++)
+ {
+ u256 v = 0;
+ if (!(i == 1 || (i == 3 && j == 2)))
+ v = i * 0x10 + j;
+ data[i * 3 + j] = v;
+ }
+ BOOST_CHECK(callContractFunction("del()") == encodeArgs(data));
+}
+
BOOST_AUTO_TEST_CASE(memory_arrays_index_access_write)
{
char const* sourceCode = R"(
@@ -4738,6 +4806,201 @@ BOOST_AUTO_TEST_CASE(memory_arrays_dynamic_index_access_write)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x20), u256(4), data));
}
+BOOST_AUTO_TEST_CASE(memory_structs_read_write)
+{
+ char const* sourceCode = R"(
+ contract Test {
+ struct S { uint8 x; uint16 y; uint z; uint8[2] a; }
+ S[5] data;
+ function testInit() returns (uint8 x, uint16 y, uint z, uint8 a, bool flag) {
+ S[2] memory d;
+ x = d[0].x;
+ y = d[0].y;
+ z = d[0].z;
+ a = d[0].a[1];
+ flag = true;
+ }
+ function testCopyRead() returns (uint8 x, uint16 y, uint z, uint8 a) {
+ data[2].x = 1;
+ data[2].y = 2;
+ data[2].z = 3;
+ data[2].a[1] = 4;
+ S memory s = data[2];
+ x = s.x;
+ y = s.y;
+ z = s.z;
+ a = s.a[1];
+ }
+ function testAssign() returns (uint8 x, uint16 y, uint z, uint8 a) {
+ S memory s;
+ s.x = 1;
+ s.y = 2;
+ s.z = 3;
+ s.a[1] = 4;
+ x = s.x;
+ y = s.y;
+ z = s.z;
+ a = s.a[1];
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Test");
+
+ BOOST_CHECK(callContractFunction("testInit()") == encodeArgs(u256(0), u256(0), u256(0), u256(0), true));
+ BOOST_CHECK(callContractFunction("testCopyRead()") == encodeArgs(u256(1), u256(2), u256(3), u256(4)));
+ BOOST_CHECK(callContractFunction("testAssign()") == encodeArgs(u256(1), u256(2), u256(3), u256(4)));
+}
+
+BOOST_AUTO_TEST_CASE(memory_structs_as_function_args)
+{
+ char const* sourceCode = R"(
+ contract Test {
+ struct S { uint8 x; uint16 y; uint z; }
+ function test() returns (uint x, uint y, uint z) {
+ S memory data = combine(1, 2, 3);
+ x = extract(data, 0);
+ y = extract(data, 1);
+ z = extract(data, 2);
+ }
+ function extract(S s, uint which) internal returns (uint x) {
+ if (which == 0) return s.x;
+ else if (which == 1) return s.y;
+ else return s.z;
+ }
+ function combine(uint8 x, uint16 y, uint z) internal returns (S s) {
+ s.x = x;
+ s.y = y;
+ s.z = z;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Test");
+
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3)));
+}
+
+BOOST_AUTO_TEST_CASE(memory_structs_nested)
+{
+ char const* sourceCode = R"(
+ contract Test {
+ struct S { uint8 x; uint16 y; uint z; }
+ struct X { uint8 x; S s; }
+ function test() returns (uint a, uint x, uint y, uint z) {
+ X memory d = combine(1, 2, 3, 4);
+ a = extract(d, 0);
+ x = extract(d, 1);
+ y = extract(d, 2);
+ z = extract(d, 3);
+ }
+ function extract(X s, uint which) internal returns (uint x) {
+ if (which == 0) return s.x;
+ else if (which == 1) return s.s.x;
+ else if (which == 2) return s.s.y;
+ else return s.s.z;
+ }
+ function combine(uint8 a, uint8 x, uint16 y, uint z) internal returns (X s) {
+ s.x = a;
+ s.s.x = x;
+ s.s.y = y;
+ s.s.z = z;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Test");
+
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(1), u256(2), u256(3), u256(4)));
+}
+
+BOOST_AUTO_TEST_CASE(memory_structs_nested_load)
+{
+ char const* sourceCode = R"(
+ contract Test {
+ struct S { uint8 x; uint16 y; uint z; }
+ struct X { uint8 x; S s; uint8[2] a; }
+ X m_x;
+ function load() returns (uint a, uint x, uint y, uint z, uint a1, uint a2) {
+ m_x.x = 1;
+ m_x.s.x = 2;
+ m_x.s.y = 3;
+ m_x.s.z = 4;
+ m_x.a[0] = 5;
+ m_x.a[1] = 6;
+ X memory d = m_x;
+ a = d.x;
+ x = d.s.x;
+ y = d.s.y;
+ z = d.s.z;
+ a1 = d.a[0];
+ a2 = d.a[1];
+ }
+ function store() returns (uint a, uint x, uint y, uint z, uint a1, uint a2) {
+ X memory d;
+ d.x = 1;
+ d.s.x = 2;
+ d.s.y = 3;
+ d.s.z = 4;
+ d.a[0] = 5;
+ d.a[1] = 6;
+ m_x = d;
+ a = m_x.x;
+ x = m_x.s.x;
+ y = m_x.s.y;
+ z = m_x.s.z;
+ a1 = m_x.a[0];
+ a2 = m_x.a[1];
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Test");
+
+ auto out = encodeArgs(u256(1), u256(2), u256(3), u256(4), u256(5), u256(6));
+ BOOST_CHECK(callContractFunction("load()") == out);
+ BOOST_CHECK(callContractFunction("store()") == out);
+}
+
+BOOST_AUTO_TEST_CASE(struct_constructor_nested)
+{
+ char const* sourceCode = R"(
+ contract C {
+ struct X { uint x1; uint x2; }
+ struct S { uint s1; uint[3] s2; X s3; }
+ S s;
+ function C() {
+ uint[3] memory s2;
+ s2[1] = 9;
+ s = S(1, s2, X(4, 5));
+ }
+ function get() returns (uint s1, uint[3] s2, uint x1, uint x2)
+ {
+ s1 = s.s1;
+ s2 = s.s2;
+ x1 = s.s3.x1;
+ x2 = s.s3.x2;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+
+ auto out = encodeArgs(u256(1), u256(0), u256(9), u256(0), u256(4), u256(5));
+ BOOST_CHECK(callContractFunction("get()") == out);
+}
+
+BOOST_AUTO_TEST_CASE(struct_named_constructor)
+{
+ char const* sourceCode = R"(
+ contract C {
+ struct S { uint a; bool x; }
+ S public s;
+ function C() {
+ s = S({a: 1, x: true});
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+
+ BOOST_CHECK(callContractFunction("s()") == encodeArgs(u256(1), true));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/libsolidity/SolidityNameAndTypeResolution.cpp b/libsolidity/SolidityNameAndTypeResolution.cpp
index 765593c5..50fcdbbe 100644
--- a/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -403,6 +403,23 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
BOOST_CHECK(derived->getDefinedFunctions()[0]->isFullyImplemented());
}
+BOOST_AUTO_TEST_CASE(abstract_contract_with_overload)
+{
+ ASTPointer<SourceUnit> sourceUnit;
+ char const* text = R"(
+ contract base { function foo(bool); }
+ contract derived is base { function foo(uint) {} }
+ )";
+ ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed");
+ std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->getNodes();
+ ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[0].get());
+ ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[1].get());
+ BOOST_REQUIRE(base);
+ BOOST_CHECK(!base->isFullyImplemented());
+ BOOST_REQUIRE(derived);
+ BOOST_CHECK(!derived->isFullyImplemented());
+}
+
BOOST_AUTO_TEST_CASE(create_abstract_contract)
{
ASTPointer<SourceUnit> sourceUnit;
@@ -1900,6 +1917,18 @@ BOOST_AUTO_TEST_CASE(storage_location_local_variables)
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode));
}
+BOOST_AUTO_TEST_CASE(no_mappings_in_memory_array)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() {
+ mapping(uint=>uint)[] memory x;
+ }
+ }
+ )";
+ BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
+}
+
BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable)
{
char const* sourceCode = R"(
@@ -1931,6 +1960,20 @@ BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable)
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
+BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint[] data;
+ function f() {
+ var x = data;
+ delete x;
+ }
+ }
+ )";
+ BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
+}
+
BOOST_AUTO_TEST_CASE(assignment_mem_storage_variable_directly)
{
char const* sourceCode = R"(
@@ -2000,6 +2043,60 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible)
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
+BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() {
+ uint[] memory x;
+ x.length = 2;
+ }
+ }
+ )";
+ BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(struct_constructor)
+{
+ char const* sourceCode = R"(
+ contract C {
+ struct S { uint a; bool x; }
+ function f() {
+ S memory s = S(1, true);
+ }
+ }
+ )";
+ BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode));
+}
+
+BOOST_AUTO_TEST_CASE(struct_constructor_nested)
+{
+ char const* sourceCode = R"(
+ contract C {
+ struct X { uint x1; uint x2; }
+ struct S { uint s1; uint[3] s2; X s3; }
+ function f() {
+ uint[3] memory s2;
+ S memory s = S(1, s2, X(4, 5));
+ }
+ }
+ )";
+ BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode));
+}
+
+BOOST_AUTO_TEST_CASE(struct_named_constructor)
+{
+ char const* sourceCode = R"(
+ contract C {
+ struct S { uint a; bool x; }
+ function f() {
+ S memory s = S({a: 1, x: true});
+ }
+ }
+ )";
+ BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/libsolidity/SolidityWallet.cpp b/libsolidity/SolidityWallet.cpp
index 09820b87..ba8f198f 100644
--- a/libsolidity/SolidityWallet.cpp
+++ b/libsolidity/SolidityWallet.cpp
@@ -200,17 +200,17 @@ contract multiowned {
}
// the number of owners that must confirm the same operation before it is run.
- uint m_required;
+ uint public m_required;
// pointer used to find a free slot in m_owners
- uint m_numOwners;
+ uint public m_numOwners;
// list of owners
- uint[256] m_owners;
+ uint[256] public m_owners;
uint constant c_maxOwners = 250;
// index on the list of owners to allow reverse lookup
- mapping(uint => uint) m_ownerIndex;
+ mapping(uint => uint) public m_ownerIndex;
// the ongoing operations.
- mapping(bytes32 => PendingState) m_pending;
- bytes32[] m_pendingIndex;
+ mapping(bytes32 => PendingState) public m_pending;
+ bytes32[] public m_pendingIndex;
}
// inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable)
@@ -251,9 +251,9 @@ contract daylimit is multiowned {
}
// determines today's index.
function today() private constant returns (uint) { return now / 1 days; }
- uint m_spentToday;
- uint m_dailyLimit;
- uint m_lastDay;
+ uint public m_spentToday;
+ uint public m_dailyLimit;
+ uint public m_lastDay;
}
// interface contract for multisig proxy contracts; see below for docs.
contract multisig {
@@ -275,11 +275,14 @@ contract Wallet is multisig, multiowned, daylimit {
uint value;
bytes data;
}
+ /*
// logged events:
// Funds has arrived into the wallet (record how much).
event Deposit(address from, uint value);
// Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
event SingleTransact(address owner, uint value, address to, bytes data);
+ // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
+ event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data);*/
// constructor - just pass on the owner arra to the multiowned.
event Created();
function Wallet() {
@@ -299,7 +302,7 @@ contract Wallet is multisig, multiowned, daylimit {
// If not, goes into multisig process. We provide a hash on return to allow the sender to provide
// shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
// and _data arguments). They still get the option of using them if they want, anyways.
- function execute(address _to, uint _value, bytes _data) onlyowner external returns (bytes32 _r) {
+ function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 _r) {
// first, take the opportunity to check that we're under the daily limit.
if (underLimit(_value)) {
SingleTransact(msg.sender, _value, _to, _data);
@@ -332,8 +335,14 @@ contract Wallet is multisig, multiowned, daylimit {
delete m_txs[m_pendingIndex[i]];
super.clearPending();
}
+ // // internally confirm transaction with all of the info. returns true iff confirmed good and executed.
+ // function confirmVerbose(bytes32 _h, address _to, uint _value, bytes _data) private onlymanyowners(_h) returns (bool) {
+ // _to.call.value(_value)(_data);
+ // MultiTransact("out", msg.sender, _h, _value, _to);
+ // return true;
+ // }
// pending transactions we have at present.
- mapping (bytes32 => Transaction) m_txs;
+ mapping (bytes32 => Transaction) public m_txs;
}
)DELIMITER";