Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
CALL vs CALLCODE vs DELEGATECALL in Solidity
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);
}
}
@Muhammad-Altabba

This comment has been minimized.

Copy link
Owner Author

Muhammad-Altabba commented Jan 11, 2019

Forked from critesjosh/Contract_calls.sol and updated for Solidity version 0.5.0 and onward.

@jamatulli

This comment has been minimized.

Copy link

jamatulli commented Jul 22, 2019

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.

@advancod

This comment has been minimized.

Copy link

advancod commented Oct 21, 2019

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
You can’t perform that action at this time.