Merge pull request #7719 from ethereum/librarySignatuŕes

Add selector member to public and external library functions.
This commit is contained in:
chriseth
2019-11-20 18:43:14 +01:00
committed by GitHub
14 changed files with 291 additions and 0 deletions
@@ -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);
}
}
// ----