mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Implement typechecked abi.encodeCall()
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
pragma abicoder v2;
|
||||
contract C {
|
||||
type UnsignedNumber is uint256;
|
||||
enum Enum { First, Second, Third }
|
||||
|
||||
struct Struct {
|
||||
UnsignedNumber[] dynamicArray;
|
||||
uint256 justAnInt;
|
||||
string name;
|
||||
bytes someBytes;
|
||||
Enum theEnum;
|
||||
}
|
||||
|
||||
function callMeMaybe(Struct calldata _data, int256 _intVal, string memory _nameVal) external pure {
|
||||
assert(_data.dynamicArray.length == 3);
|
||||
assert(UnsignedNumber.unwrap(_data.dynamicArray[0]) == 0);
|
||||
assert(UnsignedNumber.unwrap(_data.dynamicArray[1]) == 1);
|
||||
assert(UnsignedNumber.unwrap(_data.dynamicArray[2]) == 2);
|
||||
assert(_data.justAnInt == 6);
|
||||
assert(keccak256(bytes(_data.name)) == keccak256("StructName"));
|
||||
assert(keccak256(_data.someBytes) == keccak256(bytes("1234")));
|
||||
assert(_data.theEnum == Enum.Second);
|
||||
assert(_intVal == 5);
|
||||
assert(keccak256(bytes(_nameVal)) == keccak256("TestName"));
|
||||
}
|
||||
|
||||
function callExternal() public returns (bool) {
|
||||
Struct memory structToSend;
|
||||
structToSend.dynamicArray = new UnsignedNumber[](3);
|
||||
structToSend.dynamicArray[0] = UnsignedNumber.wrap(0);
|
||||
structToSend.dynamicArray[1] = UnsignedNumber.wrap(1);
|
||||
structToSend.dynamicArray[2] = UnsignedNumber.wrap(2);
|
||||
structToSend.justAnInt = 6;
|
||||
structToSend.name = "StructName";
|
||||
structToSend.someBytes = bytes("1234");
|
||||
structToSend.theEnum = Enum.Second;
|
||||
|
||||
(bool success,) = address(this).call(abi.encodeCall(this.callMeMaybe, (
|
||||
structToSend,
|
||||
5,
|
||||
"TestName"
|
||||
)));
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// callExternal() -> true
|
||||
@@ -0,0 +1,63 @@
|
||||
pragma abicoder v2;
|
||||
|
||||
contract C {
|
||||
bool sideEffectRan = false;
|
||||
|
||||
function(uint256, string memory) external fPointer;
|
||||
function fExternal(uint256 p, string memory t) external {}
|
||||
string xstor;
|
||||
function getExternalFunctionPointer() public returns (function(uint256, string memory) external) {
|
||||
sideEffectRan = true;
|
||||
return this.fExternal;
|
||||
}
|
||||
|
||||
function fSignatureFromLiteral() public pure returns (bytes memory) {
|
||||
return abi.encodeWithSignature("fExternal(uint256,string)", 1, "123");
|
||||
}
|
||||
function fSignatureFromLiteralCall() public view returns (bytes memory) {
|
||||
return abi.encodeCall(this.fExternal, (1, "123"));
|
||||
}
|
||||
function fSignatureFromMemory() public pure returns (bytes memory) {
|
||||
string memory x = "fExternal(uint256,string)";
|
||||
return abi.encodeWithSignature(x, 1, "123");
|
||||
}
|
||||
function fSignatureFromMemoryCall() public view returns (bytes memory) {
|
||||
return abi.encodeCall(this.fExternal, (1,"123"));
|
||||
}
|
||||
function fSignatureFromMemorys() public returns (bytes memory) {
|
||||
xstor = "fExternal(uint256,string)";
|
||||
return abi.encodeWithSignature(xstor, 1, "123");
|
||||
}
|
||||
function fPointerCall() public returns(bytes memory) {
|
||||
fPointer = this.fExternal;
|
||||
return abi.encodeCall(fPointer, (1, "123"));
|
||||
}
|
||||
function fLocalPointerCall() public returns(bytes memory) {
|
||||
function(uint256, string memory) external localFunctionPointer = this.fExternal;
|
||||
return abi.encodeCall(localFunctionPointer, (1, "123"));
|
||||
}
|
||||
function fReturnedFunctionPointer() public returns (bytes memory) {
|
||||
return abi.encodeCall(getExternalFunctionPointer(), (1, "123"));
|
||||
}
|
||||
|
||||
function assertConsistentSelectors() public {
|
||||
assert(keccak256(fSignatureFromLiteral()) == keccak256(fSignatureFromLiteralCall()));
|
||||
assert(keccak256(fSignatureFromMemory()) == keccak256(fSignatureFromMemoryCall()));
|
||||
assert(keccak256(fSignatureFromMemoryCall()) == keccak256(fSignatureFromMemorys()));
|
||||
assert(keccak256(fPointerCall()) == keccak256(fSignatureFromLiteral()));
|
||||
assert(keccak256(fLocalPointerCall()) == keccak256(fSignatureFromLiteral()));
|
||||
assert(keccak256(fReturnedFunctionPointer()) == keccak256(fSignatureFromLiteral()));
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// assertConsistentSelectors() ->
|
||||
// fSignatureFromLiteral() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0
|
||||
// fSignatureFromLiteralCall() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0
|
||||
// fSignatureFromMemory() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0
|
||||
// fSignatureFromMemoryCall() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0
|
||||
// fSignatureFromMemorys() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0
|
||||
// fPointerCall() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0
|
||||
// fLocalPointerCall() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0
|
||||
// fReturnedFunctionPointer() -> 0x20, 0x84, 23450202028776381066253055403048136312616272755117076566855971503345107992576, 26959946667150639794667015087019630673637144422540572481103610249216, 1725436586697640946858688965569256363112777243042596638790631055949824, 86060793054017993816230018372407419485142305772921726565498526629888, 0
|
||||
@@ -0,0 +1,28 @@
|
||||
pragma abicoder v2;
|
||||
|
||||
contract D {
|
||||
function something() external pure {}
|
||||
}
|
||||
|
||||
contract C {
|
||||
function something() external pure {}
|
||||
function test() external returns (bytes4) {
|
||||
function() external[2] memory x;
|
||||
x[0] = this.something;
|
||||
x[1] = (new D()).something;
|
||||
function() external f = x[1];
|
||||
bytes memory a = abi.encodeCall(x[0], ());
|
||||
bytes memory b = abi.encodeCall(x[1], ());
|
||||
bytes memory c = abi.encodeCall(f, ());
|
||||
assert(a.length == 4 && b.length == 4 && c.length == 4);
|
||||
assert(bytes4(a) == bytes4(b));
|
||||
assert(bytes4(a) == bytes4(c));
|
||||
assert(bytes4(a) == f.selector);
|
||||
return bytes4(a);
|
||||
}
|
||||
}
|
||||
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 0xa7a0d53700000000000000000000000000000000000000000000000000000000
|
||||
@@ -0,0 +1,48 @@
|
||||
pragma abicoder v2;
|
||||
|
||||
contract C {
|
||||
bool sideEffectRan = false;
|
||||
|
||||
function fNoArgs() external {}
|
||||
function fArray(uint[] memory x) external {}
|
||||
function fUint(uint x, uint y) external returns (uint a, uint b) {}
|
||||
|
||||
function fSignatureFromLiteralNoArgs() public pure returns (bytes memory) {
|
||||
return abi.encodeWithSignature("fNoArgs()");
|
||||
}
|
||||
function fPointerNoArgs() public view returns (bytes memory) {
|
||||
return abi.encodeCall(this.fNoArgs, ());
|
||||
}
|
||||
|
||||
function fSignatureFromLiteralArray() public pure returns (bytes memory) {
|
||||
uint[] memory x;
|
||||
return abi.encodeWithSignature("fArray(uint256[])", x);
|
||||
}
|
||||
function fPointerArray() public view returns (bytes memory) {
|
||||
uint[] memory x;
|
||||
return abi.encodeCall(this.fArray, x);
|
||||
}
|
||||
|
||||
function fSignatureFromLiteralUint() public pure returns (bytes memory) {
|
||||
return abi.encodeWithSignature("fUint(uint256,uint256)", 12, 13);
|
||||
}
|
||||
function fPointerUint() public view returns (bytes memory) {
|
||||
return abi.encodeCall(this.fUint, (12,13));
|
||||
}
|
||||
|
||||
function assertConsistentSelectors() public view {
|
||||
assert(keccak256(fSignatureFromLiteralNoArgs()) == keccak256(fPointerNoArgs()));
|
||||
assert(keccak256(fSignatureFromLiteralArray()) == keccak256(fPointerArray()));
|
||||
assert(keccak256(fSignatureFromLiteralUint()) == keccak256(fPointerUint()));
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// assertConsistentSelectors() ->
|
||||
// fSignatureFromLiteralNoArgs() -> 0x20, 0x04, 12200448252684243758085936796735499259670113115893304444050964496075123064832
|
||||
// fPointerNoArgs() -> 0x20, 4, 12200448252684243758085936796735499259670113115893304444050964496075123064832
|
||||
// fSignatureFromLiteralArray() -> 0x20, 0x44, 4612216551196396486909126966576324289294165774260092952932219511233230929920, 862718293348820473429344482784628181556388621521298319395315527974912, 0
|
||||
// fPointerArray() -> 0x20, 0x44, 4612216551196396486909126966576324289294165774260092952932219511233230929920, 862718293348820473429344482784628181556388621521298319395315527974912, 0
|
||||
// fPointerUint() -> 0x20, 0x44, 30372892641494467502622535050667754357470287521126424526399600764424271429632, 323519360005807677536004181044235568083645733070486869773243322990592, 350479306672958317330671196131255198757282877493027442254346933239808
|
||||
// fSignatureFromLiteralUint() -> 0x20, 0x44, 30372892641494467502622535050667754357470287521126424526399600764424271429632, 323519360005807677536004181044235568083645733070486869773243322990592, 350479306672958317330671196131255198757282877493027442254346933239808
|
||||
@@ -26,7 +26,6 @@ contract C {
|
||||
}
|
||||
struct S { uint a; string b; uint16 c; }
|
||||
function f4() public pure returns (bytes memory) {
|
||||
bytes4 x = 0x12345678;
|
||||
S memory s;
|
||||
s.a = 0x1234567;
|
||||
s.b = "Lorem ipsum dolor sit ethereum........";
|
||||
|
||||
Reference in New Issue
Block a user