Merge pull request #8987 from ethereum/sol-yul-bound-functions

[Sol->Yul] Bound functions
This commit is contained in:
chriseth
2020-05-25 16:53:33 +02:00
committed by GitHub
17 changed files with 364 additions and 15 deletions
@@ -0,0 +1,18 @@
library L {
function equals(address a, address b) internal pure returns (bool) {
return a == b;
}
}
contract C {
using L for address;
function foo(address a, address b) public returns (bool) {
return a.equals(b);
}
}
// ====
// compileViaYul: also
// ----
// foo(address, address): 0x111122223333444455556666777788889999aAaa, 0x111122223333444455556666777788889999aAaa -> true
// foo(address, address): 0x111122223333444455556666777788889999aAaa, 0x0000000000000000000000000000000000000000 -> false
@@ -0,0 +1,21 @@
library L {
function transfer(address a) internal {}
function send(address a) internal {}
}
contract C {
using L for address;
function useTransfer(address a) public {
a.transfer();
}
function useSend(address a) public {
a.send();
}
}
// ====
// compileViaYul: also
// ----
// useTransfer(address): 0x111122223333444455556666777788889999aAaa ->
// useSend(address): 0x111122223333444455556666777788889999aAaa ->
@@ -0,0 +1,19 @@
library L {
function pop(uint[2] memory a) internal {}
function push(uint[2] memory a) internal {}
}
contract C {
using L for uint[2];
function test() public {
uint[2] memory input;
input.push();
input.pop();
}
}
// ====
// compileViaYul: also
// ----
// test() ->
@@ -0,0 +1,20 @@
library L {
function xor(bool a, bool b) internal pure returns (bool) {
return a != b;
}
}
contract C {
using L for bool;
function foo(bool a, bool b) public returns (bool) {
return a.xor(b);
}
}
// ====
// compileViaYul: also
// ----
// foo(bool, bool): true, true -> false
// foo(bool, bool): true, false -> true
// foo(bool, bool): false, true -> true
// foo(bool, bool): false, false -> false
@@ -0,0 +1,21 @@
contract E {}
library L {
function foo(E e) internal pure returns (uint) {
return 42;
}
}
contract C {
using L for E;
function test() public returns (uint) {
E e = new E();
return e.foo();
}
}
// ====
// compileViaYul: also
// ----
// test() -> 42
@@ -0,0 +1,21 @@
library L {
function at(uint[] memory a, uint i) internal pure returns (uint) {
return a[i];
}
}
contract C {
using L for uint[];
function secondItem() public returns (uint) {
uint[] memory input = new uint[](2);
input[0] = 0x11;
input[1] = 0x22;
return input.at(1);
}
}
// ====
// compileViaYul: also
// ----
// secondItem() -> 0x22
@@ -0,0 +1,21 @@
library L {
enum E { A, B }
function equals(E a, E b) internal pure returns (bool) {
return a == b;
}
}
contract C {
using L for L.E;
function equalsA(uint choice) public returns (bool) {
L.E x = L.E.A;
return x.equals(L.E(choice));
}
}
// ====
// compileViaYul: also
// ----
// equalsA(uint256): 0 -> true
// equalsA(uint256): 1 -> false
@@ -0,0 +1,23 @@
library L {
// NOTE: External function takes up two stack slots
function double(function(uint) external pure returns (uint) f, uint x) internal pure returns (uint) {
return f(x) * 2;
}
}
contract C {
using L for function(uint) external pure returns (uint);
function identity(uint x) external pure returns (uint) {
return x;
}
function test(uint value) public returns (uint) {
return this.identity.double(value);
}
}
// ====
// compileViaYul: also
// ----
// test(uint256): 5 -> 10
@@ -0,0 +1,21 @@
library L {
function at(uint[2] memory a, uint i) internal pure returns (uint) {
return a[i];
}
}
contract C {
using L for uint[2];
function secondItem() public returns (uint) {
uint[2] memory input;
input[0] = 0x11;
input[1] = 0x22;
return input.at(1);
}
}
// ====
// compileViaYul: also
// ----
// secondItem() -> 0x22
@@ -0,0 +1,17 @@
library L {
function add(bytes2 a, bytes2 b) internal pure returns (bytes2) {
return bytes2(uint16(a) + uint16(b));
}
}
contract C {
using L for bytes2;
function sum(bytes2 a, bytes2 b) public returns (bytes2) {
return a.add(b);
}
}
// ====
// compileViaYul: also
// ----
// sum(bytes2, bytes2): left(0x1100), left(0x0022) -> left(0x1122)
@@ -0,0 +1,22 @@
library L {
function selector(function(uint) internal pure returns (uint) f, uint x) internal pure returns (uint) {
return f(x) * 2;
}
}
contract C {
using L for function(uint) internal pure returns (uint);
function identity(uint x) internal pure returns (uint) {
return x;
}
function test(uint value) public returns (uint) {
return identity.selector(value);
}
}
// ====
// compileViaYul: also
// ----
// test(uint256): 5 -> 10
@@ -0,0 +1,17 @@
library L {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
}
contract C {
using L for uint256;
function foo(uint256 a, uint256 b) public returns (uint256) {
return a.add(b);
}
}
// ====
// compileViaYul: also
// ----
// foo(uint256, uint256): 8, 42 -> 50
@@ -0,0 +1,22 @@
interface I {}
contract E is I {}
library L {
function foo(I i) internal pure returns (uint) {
return 42;
}
}
contract C {
using L for I;
function test() public returns (uint) {
E e = new E();
return I(e).foo();
}
}
// ====
// compileViaYul: also
// ----
// test() -> 42
@@ -0,0 +1,22 @@
library L {
function double(function(uint) internal pure returns (uint) f, uint x) internal pure returns (uint) {
return f(x) * 2;
}
}
contract C {
using L for function(uint) internal pure returns (uint);
function identity(uint x) internal pure returns (uint) {
return x;
}
function test(uint value) public returns (uint) {
return identity.double(value);
}
}
// ====
// compileViaYul: also
// ----
// test(uint256): 5 -> 10
@@ -0,0 +1,22 @@
library L {
function at(mapping(uint => uint) storage a, uint i) internal view returns (uint) {
return a[i];
}
}
contract C {
using L for mapping(uint => uint);
mapping(uint => uint) map;
function mapValue(uint a) public returns (uint) {
map[42] = 0x24;
map[66] = 0x66;
return map.at(a);
}
}
// ====
// compileViaYul: also
// ----
// mapValue(uint256): 42 -> 0x24
@@ -0,0 +1,18 @@
library L {
function at(string memory a, uint i) internal pure returns (uint8) {
return uint8(bytes(a)[i]);
}
}
contract C {
using L for string;
function secondChar() public returns (uint8) {
string memory input = "abc";
return input.at(1);
}
}
// ====
// compileViaYul: also
// ----
// secondChar() -> 98