mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7701 from ethereum/libraryAddresses
Allow obtaining the address of a library by conversion to ``address``.
This commit is contained in:
commit
6f500f0632
@ -1,6 +1,7 @@
|
||||
### 0.5.13 (unreleased)
|
||||
|
||||
Language Features:
|
||||
* Allow to obtain the address of a linked library with ``address(LibraryName)``.
|
||||
|
||||
|
||||
Compiler Features:
|
||||
|
@ -178,6 +178,9 @@ custom types without the overhead of external function calls:
|
||||
}
|
||||
}
|
||||
|
||||
It is possible to obtain the address of a library by converting
|
||||
the library type to the ``address`` type, i.e. using ``address(LibraryName)``.
|
||||
|
||||
As the compiler cannot know where the library will be
|
||||
deployed at, these addresses have to be filled into the
|
||||
final bytecode by a linker
|
||||
|
@ -3373,6 +3373,15 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current
|
||||
return members;
|
||||
}
|
||||
|
||||
BoolResult TypeType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||
{
|
||||
if (auto const* address = dynamic_cast<AddressType const*>(&_convertTo))
|
||||
if (address->stateMutability() == StateMutability::NonPayable)
|
||||
if (auto const* contractType = dynamic_cast<ContractType const*>(m_actualType))
|
||||
return contractType->contractDefinition().isLibrary();
|
||||
return isImplicitlyConvertibleTo(_convertTo);
|
||||
}
|
||||
|
||||
ModifierType::ModifierType(ModifierDefinition const& _modifier)
|
||||
{
|
||||
TypePointers params;
|
||||
|
@ -1287,6 +1287,7 @@ public:
|
||||
std::string toString(bool _short) const override { return "type(" + m_actualType->toString(_short) + ")"; }
|
||||
MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
|
||||
|
||||
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
private:
|
||||
TypePointer m_actualType;
|
||||
};
|
||||
|
@ -475,7 +475,22 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
solAssert(_functionCall.arguments().size() == 1, "");
|
||||
solAssert(_functionCall.names().empty(), "");
|
||||
acceptAndConvert(*_functionCall.arguments().front(), *_functionCall.annotation().type);
|
||||
auto const& expression = *_functionCall.arguments().front();
|
||||
auto const& targetType = *_functionCall.annotation().type;
|
||||
if (auto const* typeType = dynamic_cast<TypeType const*>(expression.annotation().type))
|
||||
if (auto const* addressType = dynamic_cast<AddressType const*>(&targetType))
|
||||
{
|
||||
auto const* contractType = dynamic_cast<ContractType const*>(typeType->actualType());
|
||||
solAssert(
|
||||
contractType &&
|
||||
contractType->contractDefinition().isLibrary() &&
|
||||
addressType->stateMutability() == StateMutability::NonPayable,
|
||||
""
|
||||
);
|
||||
m_context.appendLibraryAddress(contractType->contractDefinition().fullyQualifiedName());
|
||||
return false;
|
||||
}
|
||||
acceptAndConvert(expression, targetType);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
56
test/libsolidity/semanticTests/libraries/library_address.sol
Normal file
56
test/libsolidity/semanticTests/libraries/library_address.sol
Normal file
@ -0,0 +1,56 @@
|
||||
library L {
|
||||
function f(uint256 v) external pure returns (uint) {
|
||||
return v * v;
|
||||
}
|
||||
function g(uint256 v) external returns (uint) {
|
||||
return v * v;
|
||||
}
|
||||
}
|
||||
contract C {
|
||||
function addr() public view returns (bool) {
|
||||
return address(L) == address(0);
|
||||
}
|
||||
function g(uint256 v) public view returns (uint256) {
|
||||
return L.f(v);
|
||||
}
|
||||
function h(uint256 v) public returns (uint256) {
|
||||
(bool success, bytes memory result) = address(L).delegatecall(abi.encodeWithSignature("f(uint256)", v));
|
||||
assert(success);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
function i(uint256 v) public returns (uint256) {
|
||||
(bool success, bytes memory result) = address(L).call(abi.encodeWithSignature("f(uint256)", v));
|
||||
assert(success);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
function j(uint256 v) public returns (uint256) {
|
||||
(bool success, bytes memory result) = address(L).delegatecall(abi.encodeWithSignature("g(uint256)", v));
|
||||
assert(success);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
function k(uint256 v) public returns (uint256) {
|
||||
(bool success, bytes memory result) = address(L).call(abi.encodeWithSignature("g(uint256)", v));
|
||||
assert(success);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// library: L
|
||||
// addr() -> false
|
||||
// g(uint256): 1 -> 1
|
||||
// g(uint256): 2 -> 4
|
||||
// g(uint256): 4 -> 16
|
||||
// h(uint256): 1 -> 1
|
||||
// h(uint256): 2 -> 4
|
||||
// h(uint256): 4 -> 16
|
||||
// i(uint256): 1 -> 1
|
||||
// i(uint256): 2 -> 4
|
||||
// i(uint256): 4 -> 16
|
||||
// j(uint256): 1 -> 1
|
||||
// j(uint256): 2 -> 4
|
||||
// j(uint256): 4 -> 16
|
||||
// k(uint256): 1 -> FAILURE
|
||||
// k(uint256): 2 -> FAILURE
|
||||
// k(uint256): 4 -> FAILURE
|
@ -0,0 +1,24 @@
|
||||
library L {
|
||||
function f(uint256 a, uint256 b) external {
|
||||
assert(a * a == b);
|
||||
}
|
||||
}
|
||||
contract C {
|
||||
function addr() public view returns (bool) {
|
||||
return address(L) == address(0);
|
||||
}
|
||||
function g(uint256 a, uint256 b) public returns (bool) {
|
||||
(bool success,) = address(L).delegatecall(abi.encodeWithSignature("f(uint256,uint256)", a, b));
|
||||
return success;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// library: L
|
||||
// g(uint256,uint256): 1, 1 -> true
|
||||
// g(uint256,uint256): 1, 2 -> false
|
||||
// g(uint256,uint256): 2, 3 -> false
|
||||
// g(uint256,uint256): 2, 4 -> true
|
||||
// g(uint256,uint256): 2, 5 -> false
|
||||
// g(uint256,uint256): 4, 15 -> false
|
||||
// g(uint256,uint256): 4, 16 -> true
|
||||
// g(uint256,uint256): 4, 17 -> false
|
@ -0,0 +1,8 @@
|
||||
library L {
|
||||
}
|
||||
contract C {
|
||||
function f() public pure returns (address) {
|
||||
return address(L);
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,9 @@
|
||||
library L {
|
||||
}
|
||||
contract C {
|
||||
function f() public pure returns (address payable) {
|
||||
return address(L);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (99-109): Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable.
|
Loading…
Reference in New Issue
Block a user