mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add selector member to public and external library functions.
This commit is contained in:
parent
6a993152d5
commit
a0ae36ba70
@ -1,6 +1,7 @@
|
||||
### 0.5.14 (unreleased)
|
||||
|
||||
Language Features:
|
||||
* Allow to obtain the selector of public or external library functions via a member ``.selector``.
|
||||
|
||||
|
||||
Compiler Features:
|
||||
|
@ -2962,6 +2962,20 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
|
||||
);
|
||||
return members;
|
||||
}
|
||||
case Kind::DelegateCall:
|
||||
{
|
||||
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(m_declaration);
|
||||
solAssert(functionDefinition, "");
|
||||
solAssert(functionDefinition->visibility() != Declaration::Visibility::Private, "");
|
||||
if (functionDefinition->visibility() != Declaration::Visibility::Internal)
|
||||
{
|
||||
auto const* contract = dynamic_cast<ContractDefinition const*>(m_declaration->scope());
|
||||
solAssert(contract, "");
|
||||
solAssert(contract->isLibrary(), "");
|
||||
return {{"selector", TypeProvider::fixedBytes(4)}};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
default:
|
||||
return MemberList::MemberMap();
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
library L {
|
||||
function f(uint256[] storage x) public pure returns (uint256) {
|
||||
return 23;
|
||||
}
|
||||
}
|
||||
contract C {
|
||||
uint256[] y;
|
||||
string x;
|
||||
constructor() public { y.push(42); }
|
||||
function f() public view returns (uint256) {
|
||||
return L.f(y);
|
||||
}
|
||||
function g() public returns (bool, uint256) {
|
||||
uint256 ys;
|
||||
assembly { ys := y_slot }
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.f.selector, ys));
|
||||
return (success, success ? abi.decode(data,(uint256)) : 0);
|
||||
}
|
||||
function h() public returns (bool, uint256) {
|
||||
uint256 ys;
|
||||
assembly { ys := y_slot }
|
||||
(bool success, bytes memory data) = address(L).call(abi.encodeWithSelector(L.f.selector, ys));
|
||||
return (success, success ? abi.decode(data,(uint256)) : 0);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >homestead
|
||||
// ----
|
||||
// library: L
|
||||
// f() -> 23
|
||||
// g() -> true, 23
|
||||
// h() -> true, 23
|
@ -0,0 +1,32 @@
|
||||
library L {
|
||||
function f(uint256[] storage x) public view returns (uint256) {
|
||||
return x.length;
|
||||
}
|
||||
}
|
||||
contract C {
|
||||
uint256[] y;
|
||||
string x;
|
||||
constructor() public { y.push(42); }
|
||||
function f() public view returns (uint256) {
|
||||
return L.f(y);
|
||||
}
|
||||
function g() public returns (bool, uint256) {
|
||||
uint256 ys;
|
||||
assembly { ys := y_slot }
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.f.selector, ys));
|
||||
return (success, success ? abi.decode(data,(uint256)) : 0);
|
||||
}
|
||||
function h() public returns (bool, uint256) {
|
||||
uint256 ys;
|
||||
assembly { ys := y_slot }
|
||||
(bool success, bytes memory data) = address(L).call(abi.encodeWithSelector(L.f.selector, ys));
|
||||
return (success, success ? abi.decode(data,(uint256)) : 0);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >homestead
|
||||
// ----
|
||||
// library: L
|
||||
// f() -> 1
|
||||
// g() -> true, 1
|
||||
// h() -> true, 0 # this is bad - this should fail! #
|
@ -0,0 +1,31 @@
|
||||
library L {
|
||||
function f(uint256[] storage x) public view returns (uint256) {
|
||||
return 84;
|
||||
}
|
||||
}
|
||||
contract C {
|
||||
uint256[] y;
|
||||
constructor() public { y.push(42); }
|
||||
function f() public view returns (uint256) {
|
||||
return L.f(y);
|
||||
}
|
||||
function g() public returns (bool, uint256) {
|
||||
uint256 ys;
|
||||
assembly { ys := y_slot }
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.f.selector, ys));
|
||||
return (success, success ? abi.decode(data,(uint256)) : 0);
|
||||
}
|
||||
function h() public returns (bool, uint256) {
|
||||
uint256 ys;
|
||||
assembly { ys := y_slot }
|
||||
(bool success, bytes memory data) = address(L).call(abi.encodeWithSelector(L.f.selector, ys));
|
||||
return (success, success ? abi.decode(data,(uint256)) : 0);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >homestead
|
||||
// ----
|
||||
// library: L
|
||||
// f() -> 84
|
||||
// g() -> true, 84
|
||||
// h() -> true, 84
|
@ -0,0 +1,31 @@
|
||||
contract D {
|
||||
uint public x;
|
||||
constructor() public { x = 42; }
|
||||
}
|
||||
library L {
|
||||
function f(D d) public view returns (uint256) {
|
||||
return d.x();
|
||||
}
|
||||
}
|
||||
contract C {
|
||||
D d;
|
||||
constructor() public { d = new D(); }
|
||||
function f() public view returns (uint256) {
|
||||
return L.f(d);
|
||||
}
|
||||
function g() public returns (bool, uint256) {
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.f.selector, d));
|
||||
return (success, success ? abi.decode(data,(uint256)) : 0);
|
||||
}
|
||||
function h() public returns (bool, uint256) {
|
||||
(bool success, bytes memory data) = address(L).call(abi.encodeWithSelector(L.f.selector, d));
|
||||
return (success, success ? abi.decode(data,(uint256)) : 0);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >homestead
|
||||
// ----
|
||||
// library: L
|
||||
// f() -> 42
|
||||
// g() -> true, 42
|
||||
// h() -> true, 42
|
@ -0,0 +1,30 @@
|
||||
library L {
|
||||
function f(uint256 x) external returns (uint) { return x; }
|
||||
function g(uint256[] storage s) external returns (uint) { return s.length; }
|
||||
function h(uint256[] memory m) public returns (uint) { return m.length; }
|
||||
}
|
||||
contract C {
|
||||
uint256[] s;
|
||||
constructor() public { while (s.length < 42) s.push(0); }
|
||||
function f() public returns (bool, bool, uint256) {
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.f.selector, 7));
|
||||
return (L.f.selector == bytes4(keccak256("f(uint256)")), success, abi.decode(data, (uint256)));
|
||||
}
|
||||
function g() public returns (bool, bool, uint256) {
|
||||
uint256 s_ptr;
|
||||
assembly { s_ptr := s_slot }
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.g.selector, s_ptr));
|
||||
return (L.g.selector == bytes4(keccak256("g(uint256[] storage)")), success, abi.decode(data, (uint256)));
|
||||
}
|
||||
function h() public returns (bool, bool, uint256) {
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.h.selector, new uint256[](23)));
|
||||
return (L.h.selector == bytes4(keccak256("h(uint256[])")), success, abi.decode(data, (uint256)));
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >homestead
|
||||
// ----
|
||||
// library: L
|
||||
// f() -> true, true, 7
|
||||
// g() -> true, true, 42
|
||||
// h() -> true, true, 23
|
@ -0,0 +1,27 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
library L {
|
||||
struct S { uint256 a; }
|
||||
function f(S storage s) external returns (uint) { return s.a; }
|
||||
function g(S memory m) public returns (uint) { return m.a; }
|
||||
}
|
||||
contract C {
|
||||
L.S s;
|
||||
constructor() public { s.a = 42; }
|
||||
|
||||
function f() public returns (bool, bool, uint256) {
|
||||
uint256 s_ptr;
|
||||
assembly { s_ptr := s_slot }
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.f.selector, s_ptr));
|
||||
return (L.f.selector == bytes4(keccak256("f(L.S storage)")), success, abi.decode(data, (uint256)));
|
||||
}
|
||||
function g() public returns (bool, bool, uint256) {
|
||||
(bool success, bytes memory data) = address(L).delegatecall(abi.encodeWithSelector(L.g.selector, L.S(23)));
|
||||
return (L.g.selector == bytes4(keccak256("g(L.S)")), success, abi.decode(data, (uint256)));
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >homestead
|
||||
// ----
|
||||
// library: L
|
||||
// f() -> true, true, 42
|
||||
// g() -> true, true, 23
|
@ -0,0 +1,13 @@
|
||||
library L {
|
||||
function f(uint256) external {}
|
||||
function g(uint256[] storage) external {}
|
||||
function h(uint256[] memory) public {}
|
||||
}
|
||||
contract C {
|
||||
function f() public pure returns (bytes4 a, bytes4 b, bytes4 c, bytes4 d) {
|
||||
a = L.f.selector;
|
||||
b = L.g.selector;
|
||||
c = L.h.selector;
|
||||
d = L.h.selector;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
library L {
|
||||
function f(uint256) internal {}
|
||||
}
|
||||
contract C {
|
||||
function f() public pure returns (bytes4) {
|
||||
return L.f.selector;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (126-138): Member "selector" not found or not visible after argument-dependent lookup in function (uint256).
|
@ -0,0 +1,8 @@
|
||||
library L {
|
||||
function f(uint256) private {}
|
||||
function g(uint256) public returns (uint256) {
|
||||
return f.selector;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (113-123): Member "selector" not found or not visible after argument-dependent lookup in function (uint256).
|
@ -0,0 +1,10 @@
|
||||
library L {
|
||||
function f(uint256) private {}
|
||||
}
|
||||
contract C {
|
||||
function f() public pure returns (bytes4) {
|
||||
return L.f.selector;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (125-128): Member "f" not found or not visible after argument-dependent lookup in type(library L).
|
@ -0,0 +1,10 @@
|
||||
library L {
|
||||
function f(uint256) external pure {}
|
||||
function g(uint256) external view {}
|
||||
}
|
||||
contract C {
|
||||
function f() public pure returns (bytes4, bytes4) {
|
||||
return (L.f.selector, L.g.selector);
|
||||
}
|
||||
}
|
||||
// ----
|
Loading…
Reference in New Issue
Block a user