-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
``` | ||
pragma solidity ^0.5.11; | ||
/* | ||
call | ||
- low level method available on address | ||
- not recommended | ||
- examples | ||
- call existing function | ||
- call non-existing function (trigger the fallback function) | ||
*/ | ||
contract Receiver { | ||
event Received(address caller, uint amount, string message); | ||
// NOTE: external, payable | ||
function () external payable { | ||
// NOTE: cannot take input, cannot return output | ||
emit Received(msg.sender, msg.value, "Fallback was called"); | ||
} | ||
// NOTE: inputs | ||
// NOTE: payable | ||
// NOTE: outputs | ||
function foo(string memory _message, uint _x) public payable returns (uint) { | ||
emit Received(msg.sender, msg.value, _message); | ||
// NOTE: output | ||
return _x + 1; | ||
} | ||
} | ||
contract Caller { | ||
event Response(bool success, bytes data); | ||
// NOTE: payable addr | ||
function testCallFoo(address payable _addr) public payable { | ||
// NOTE: value and gas optional | ||
// NOTE: start with ("") | ||
// NOTE: explain learn abi.encodeWithSignature | ||
// explain signature | ||
/* | ||
- function name with the parenthesised | ||
- list of parameter types | ||
- Parameter types are split by a single comma | ||
- no spaces are used | ||
- no return type | ||
(1 byte = 8 bits, 2**8, 256, hex = 0-9a-f 16 * 16 = 256) | ||
*/ | ||
// explain function selector | ||
// bytes4(keccak256(bytes(signature)) | ||
// NOTE: no space, no return type | ||
// NOTE: going to call fallback if function signature is wrong | ||
// NOTE: uint must be uint256 | ||
(bool success, bytes memory data) = _addr.call.value(msg.value).gas(5000)( | ||
abi.encodeWithSignature("foo(string,uint256)", "call foo", 123) | ||
); | ||
emit Response(success, data); | ||
} | ||
// NOTE: remove payable addr | ||
function testCallDoesNotExist(address _addr) public { | ||
// NOTE: optional value and gas | ||
(bool success, bytes memory data) = _addr.call( | ||
abi.encodeWithSignature("doesNotExist()") | ||
); | ||
emit Response(success, data); | ||
} | ||
} | ||
/* | ||
DEMO | ||
- deploy contracts | ||
- callFoo | ||
- NOTE: 2 logs | ||
- NOTE: caller | ||
- NOTE: success | ||
- NOTE: return data == (x + 1) (parseInt("0x7c") | ||
- NOTE: walk through code execution | ||
- callDoesNotExist | ||
- NOTE: 2 logs | ||
- NOTE: caller | ||
- NOTE: success | ||
- NOTE: return data = 0 | ||
*/ | ||
``` | ||
|
||
``` | ||
pragma solidity ^0.5.11; | ||
/* | ||
call - low level method available on address type | ||
examples | ||
- call existing function | ||
- call non-existing function (triggers the fallback function) | ||
*/ | ||
contract Reciever { | ||
event Received(address caller, uint amount, string message); | ||
function () external payable { | ||
emit Received(msg.sender, msg.value, "Fallback was called"); | ||
} | ||
function foo(string memory _message, uint _x) public payable returns (uint) { | ||
emit Received(msg.sender, msg.value, _message); | ||
return _x + 1; | ||
} | ||
} | ||
contract Caller { | ||
function testCallFoo(address payable _addr) public payable { | ||
_addr.call.value(msg.value).gas(5000)(""); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
``` | ||
pragma solidity ^0.5.11; | ||
/* | ||
- call is low level function to call other functions and send ether | ||
- examples | ||
call non payable function in another contract | ||
call payable function in another contract | ||
- common way to call function and send ether | ||
*/ | ||
contract Callee { | ||
uint public x; | ||
uint public value; | ||
function setX(uint _x) public returns (uint) { | ||
x = _x; | ||
return x; | ||
} | ||
// NOTE: how to return multiple outputs | ||
function setXandSendEther(uint _x) public payable returns (uint, uint) { | ||
x = _x; | ||
value = msg.value; | ||
return (x, value); | ||
} | ||
} | ||
contract Caller { | ||
// NOTE: Callee input (address) | ||
// TODO: what is the type of Callee? | ||
function callSetX(Callee _callee, uint _x) public { | ||
uint x = _callee.setX(_x); | ||
} | ||
// NOTE: payable | ||
function callSetXAndSendEther(Callee _callee, uint _x) public payable { | ||
// NOTE: fails to compiles if func does not exit or wrong parameters (unlike call) | ||
// NOTE: assigning multiple outputs | ||
(uint x, uint value) = _callee.setXandSendEther.value(msg.value)(_x); | ||
} | ||
} | ||
/* | ||
DEMO | ||
NOTE: callee = address type | ||
callSetX | ||
callSetXAndSendEther | ||
*/ | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
``` | ||
pragma solidity ^0.5.11; | ||
/* | ||
# intro | ||
- delegatecall is a low level function similar to call. | ||
- when A delegatecall B | ||
runs B's code inside A's context (storage, msg.sender, msg.value) | ||
- can upgrade contract A without changing any code inside it | ||
# explain delegatecall context | ||
# explain delegatecall upgrade | ||
# code (contract B, A) | ||
# demo | ||
# code (change storage for contract B) | ||
# demo | ||
# code (contract B2) | ||
# demo | ||
# summary | ||
- delegatecall runs code of callee in caller's context (storage, sender, value) | ||
- upgrade contract without changing the code | ||
- storage layout must be same | ||
*/ | ||
contract B { | ||
uint public num; | ||
address public sender; | ||
uint public value; | ||
function setVars(uint _num) public payable { | ||
num = _num; | ||
sender = msg.sender; | ||
value = msg.value; | ||
} | ||
} | ||
contract B2 { | ||
uint public num; | ||
address public sender; | ||
uint public value; | ||
function setVars(uint _num) public payable { | ||
num = 2 * _num; | ||
sender = msg.sender; | ||
value = msg.value; | ||
} | ||
} | ||
contract A { | ||
// NOTE: storage layout must be the same | ||
uint public num; | ||
address public sender; | ||
uint public value; | ||
function setVars(address _contract, uint _num) public payable { | ||
// NOTE: function signature (similar to call) | ||
// NOTE: uint256 | ||
(bool success, bytes memory data) = _contract.delegatecall( | ||
abi.encodeWithSignature("setVars(uint256)", _num) | ||
); | ||
} | ||
} | ||
/* | ||
DEMO | ||
deploy B | ||
deploy A | ||
- setVars | ||
- check state variables on contract A and B | ||
- note sender and value | ||
change B storage | ||
- redeploy B | ||
- setVars | ||
- check A values | ||
create B2 | ||
deploy B2 | ||
- setVars | ||
- check state variables on contract A | ||
*/ | ||
``` | ||
|
||
``` | ||
pragma solidity ^0.5.11; | ||
/* | ||
delegatecall | ||
- a low level function similar to call | ||
- when contract A delegatecall contract B | ||
it runs B's code inside A's context (storage, msg.sender, msg.value) | ||
- can upgrade contract A without changing any code inside it | ||
*/ | ||
contract B { | ||
uint public num; | ||
address public sender; | ||
uint public value; | ||
function setVars(uint _num) public payable { | ||
num = _num; | ||
sender = msg.sender; | ||
value = msg.value; | ||
} | ||
} | ||
contract B2 { | ||
uint public num; | ||
address public sender; | ||
uint public value; | ||
function setVars(uint _num) public payable { | ||
num = 2 * _num; | ||
sender = msg.sender; | ||
value = msg.value; | ||
} | ||
} | ||
contract A { | ||
uint public num; | ||
address public sender; | ||
uint public value; | ||
function setVars(address _contract, uint _num) public payable { | ||
(bool success, bytes memory data) = _contract.delegatecall( | ||
abi.encodeWithSignature("setVars(uint256)", _num) | ||
); | ||
} | ||
} | ||
``` |