-
-
Save Muhammad-Altabba/55ac6974ac9396d723fdfd792d51eb5d to your computer and use it in GitHub Desktop.
CALL vs CALLCODE vs DELEGATECALL in Solidity
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
pragma solidity ^0.5.0; | |
contract C1 { | |
uint public num; | |
address public sender; | |
function callSetNum(address c2, uint _num) public { | |
(bool res,) = c2.call(abi.encodePacked(bytes4(keccak256("setNum(uint256)")), _num)); | |
if(!res) revert(); // C2's num is set | |
} | |
function c2setNum(address _c2, uint _num) public { | |
C2 c2 = C2(_c2); | |
c2.setNum(_num); | |
} | |
// Function callcode is now disallowed (in favor of delegatecall). | |
// It is still possible to use it via inline assembly. | |
// https://solidity.readthedocs.io/en/v0.5.0/050-breaking-changes.html | |
// function callcodeSetNum(address c2, uint _num) public { | |
// bool res; | |
// In version 5.0 and upward the next line will case: | |
// TypeError: "callcode" has been deprecated in favour of "delegatecall" | |
// (res,) = c2.callcode(abi.encodePacked(bytes4(keccak256("setNum(uint256)")), _num)); | |
// if(!res) revert(); // C1's num is set | |
// } | |
function delegatecallSetNum(address c2, uint _num) public { | |
(bool res,) = c2.delegatecall(abi.encodePacked(bytes4(keccak256("setNum(uint256)")), _num)); | |
if(!res) revert(); // C1's num is set | |
} | |
} | |
contract C2 { | |
uint public num; | |
address public sender; | |
function setNum(uint _num) public { | |
num = _num; | |
sender = msg.sender; | |
// msg.sender is C1 if invoked by C1.callcodeSetNum | |
// msg.sender is C3 if invoked by C3.f1() | |
} | |
} | |
contract C3 { | |
function f1(C1 c1, C2 c2, uint _num) public { | |
c1.delegatecallSetNum((address)(c2), _num); | |
} | |
} |
I think the comment on line 41 should read callSetNum now that callcode is deprecated.
// msg.sender is C1 if invoked by C1.callcodeSetNum
should read
// msg.sender is C1 if invoked by C1.callSetNum
As an aside callcode will actually show c2 address as the msg.sender in pre-0.5.0 versions and likely will do the same in inline assembly.
Please very please
can someone explain me why the function transferDai doesnot work in the following code? you ll save my life
pragma solidity ^0.5.9;
// Adding only the ERC-20 function we need
interface DaiToken {
function balanceOf(address guy) external view returns (uint);
}
contract DaiFaucet {
address dai;
DaiToken daitoken;
constructor() public{
dai = 0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359;
daitoken = DaiToken(dai);
}
function balance() public view returns (uint) {
return daitoken.balanceOf(msg.sender); // I have dai here
}
function balanceBis() public view returns (uint) {
return daitoken.balanceOf(0x820Af9cea6CF890F36CAe589853190C622d39058); // a custom target address of mine
}
function transferdai() public {
uint value = 1;
address target = 0x820Af9cea6CF890F36CAe589853190C622d39058;
(bool res,) = dai.delegatecall(abi.encodePacked(bytes4(keccak256("transfer(address,uint256)")), target, value));
if(!res) revert();
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Forked from critesjosh/Contract_calls.sol and updated for Solidity version 0.5.0 and onward.