mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1585 from ethereum/libraryfallback
Provide fallback for linking.
This commit is contained in:
commit
9ce30e9da0
@ -1,6 +1,7 @@
|
|||||||
### 0.4.9 (unreleased)
|
### 0.4.9 (unreleased)
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
* Compiler Interface: Contracts and libraries can be referenced with a `file:` prefix to make them unique.
|
||||||
* AST: Use deterministic node identifiers.
|
* AST: Use deterministic node identifiers.
|
||||||
* Metadata: Do not include platform in the version number.
|
* Metadata: Do not include platform in the version number.
|
||||||
|
|
||||||
@ -16,9 +17,6 @@ Bugfixes:
|
|||||||
* Imports: ``import ".dir/a"`` is not a relative path. Relative paths begin with directory ``.`` or ``..``.
|
* Imports: ``import ".dir/a"`` is not a relative path. Relative paths begin with directory ``.`` or ``..``.
|
||||||
* Type checker, disallow inheritances of different kinds (e.g. a function and a modifier) of members of the same name
|
* Type checker, disallow inheritances of different kinds (e.g. a function and a modifier) of members of the same name
|
||||||
|
|
||||||
Features:
|
|
||||||
* Contracts and libraries are now unique to their source files, rather than globally.
|
|
||||||
|
|
||||||
### 0.4.7 (2016-12-15)
|
### 0.4.7 (2016-12-15)
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
@ -37,13 +37,10 @@ void LinkerObject::link(map<string, h160> const& _libraryAddresses)
|
|||||||
{
|
{
|
||||||
std::map<size_t, std::string> remainingRefs;
|
std::map<size_t, std::string> remainingRefs;
|
||||||
for (auto const& linkRef: linkReferences)
|
for (auto const& linkRef: linkReferences)
|
||||||
{
|
if (h160 const* address = matchLibrary(linkRef.second, _libraryAddresses))
|
||||||
auto it = _libraryAddresses.find(linkRef.second);
|
address->ref().copyTo(ref(bytecode).cropped(linkRef.first, 20));
|
||||||
if (it == _libraryAddresses.end())
|
|
||||||
remainingRefs.insert(linkRef);
|
|
||||||
else
|
else
|
||||||
it->second.ref().copyTo(ref(bytecode).cropped(linkRef.first, 20));
|
remainingRefs.insert(linkRef);
|
||||||
}
|
|
||||||
linkReferences.swap(remainingRefs);
|
linkReferences.swap(remainingRefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,3 +57,23 @@ string LinkerObject::toHex() const
|
|||||||
}
|
}
|
||||||
return hex;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h160 const*
|
||||||
|
LinkerObject::matchLibrary(
|
||||||
|
string const& _linkRefName,
|
||||||
|
map<string, h160> const& _libraryAddresses
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto it = _libraryAddresses.find(_linkRefName);
|
||||||
|
if (it != _libraryAddresses.end())
|
||||||
|
return &it->second;
|
||||||
|
// If the user did not supply a fully qualified library name,
|
||||||
|
// try to match only the simple libary name
|
||||||
|
size_t colon = _linkRefName.find(':');
|
||||||
|
if (colon == string::npos)
|
||||||
|
return nullptr;
|
||||||
|
it = _libraryAddresses.find(_linkRefName.substr(colon + 1));
|
||||||
|
if (it != _libraryAddresses.end())
|
||||||
|
return &it->second;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
@ -49,6 +49,12 @@ struct LinkerObject
|
|||||||
/// @returns a hex representation of the bytecode of the given object, replacing unlinked
|
/// @returns a hex representation of the bytecode of the given object, replacing unlinked
|
||||||
/// addresses by placeholders.
|
/// addresses by placeholders.
|
||||||
std::string toHex() const;
|
std::string toHex() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static h160 const* matchLibrary(
|
||||||
|
std::string const& _linkRefName,
|
||||||
|
std::map<std::string, h160> const& _libraryAddresses
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3192,7 +3192,7 @@ BOOST_AUTO_TEST_CASE(library_call_in_homestead)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "Lib");
|
compileAndRun(sourceCode, 0, "Lib");
|
||||||
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{":Lib", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs());
|
BOOST_CHECK(callContractFunction("f()") == encodeArgs());
|
||||||
BOOST_CHECK(callContractFunction("sender()") == encodeArgs(u160(m_sender)));
|
BOOST_CHECK(callContractFunction("sender()") == encodeArgs(u160(m_sender)));
|
||||||
}
|
}
|
||||||
@ -6191,7 +6191,7 @@ BOOST_AUTO_TEST_CASE(library_call)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "Lib");
|
compileAndRun(sourceCode, 0, "Lib");
|
||||||
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{":Lib", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(33) * 9));
|
BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(33) * 9));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6208,7 +6208,7 @@ BOOST_AUTO_TEST_CASE(library_stray_values)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "Lib");
|
compileAndRun(sourceCode, 0, "Lib");
|
||||||
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{":Lib", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(42)));
|
BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(42)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6341,7 +6341,7 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "Lib");
|
compileAndRun(sourceCode, 0, "Lib");
|
||||||
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{":Lib", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17)));
|
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6368,7 +6368,7 @@ BOOST_AUTO_TEST_CASE(using_library_structs)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "Lib");
|
compileAndRun(sourceCode, 0, "Lib");
|
||||||
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{":Lib", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7), u256(8)));
|
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7), u256(8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6902,7 +6902,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_int)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "D");
|
compileAndRun(sourceCode, 0, "D");
|
||||||
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{":D", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(9)) == encodeArgs(u256(2 * 9)));
|
BOOST_CHECK(callContractFunction("f(uint256)", u256(9)) == encodeArgs(u256(2 * 9)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6920,7 +6920,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_struct)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "D");
|
compileAndRun(sourceCode, 0, "D");
|
||||||
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{":D", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(3 * 7)));
|
BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(3 * 7)));
|
||||||
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(3 * 7)));
|
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(3 * 7)));
|
||||||
}
|
}
|
||||||
@ -6943,7 +6943,7 @@ BOOST_AUTO_TEST_CASE(using_for_overload)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "D");
|
compileAndRun(sourceCode, 0, "D");
|
||||||
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{":D", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7)));
|
BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7)));
|
||||||
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7)));
|
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7)));
|
||||||
}
|
}
|
||||||
@ -6962,7 +6962,7 @@ BOOST_AUTO_TEST_CASE(using_for_by_name)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "D");
|
compileAndRun(sourceCode, 0, "D");
|
||||||
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{":D", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7)));
|
BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7)));
|
||||||
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7)));
|
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7)));
|
||||||
}
|
}
|
||||||
@ -6982,7 +6982,7 @@ BOOST_AUTO_TEST_CASE(bound_function_in_var)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "D");
|
compileAndRun(sourceCode, 0, "D");
|
||||||
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{":D", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7)));
|
BOOST_CHECK(callContractFunction("f(uint256)", u256(7)) == encodeArgs(u256(6 * 7)));
|
||||||
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7)));
|
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(6 * 7)));
|
||||||
}
|
}
|
||||||
@ -7005,7 +7005,7 @@ BOOST_AUTO_TEST_CASE(bound_function_to_string)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "D");
|
compileAndRun(sourceCode, 0, "D");
|
||||||
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{":D", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"D", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(3)));
|
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(3)));
|
||||||
BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(3)));
|
BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(3)));
|
||||||
}
|
}
|
||||||
@ -7751,7 +7751,7 @@ BOOST_AUTO_TEST_CASE(payable_function_calls_library)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "L");
|
compileAndRun(sourceCode, 0, "L");
|
||||||
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{":L", m_contractAddress}});
|
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}});
|
||||||
BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7)));
|
BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user