{"id":878,"date":"2025-08-04T22:14:37","date_gmt":"2025-08-04T14:14:37","guid":{"rendered":"https:\/\/vinta.ws\/code\/?p=878"},"modified":"2026-04-06T22:53:58","modified_gmt":"2026-04-06T14:53:58","slug":"solidity-call-vs-delegatecall","status":"publish","type":"post","link":"https:\/\/vinta.ws\/code\/solidity-call-vs-delegatecall.html","title":{"rendered":"Solidity: call() vs delegatecall()"},"content":{"rendered":"<p>tl;dr: <code>delegatecall<\/code> runs in the context of the caller contract.<\/p>\n<p>The difference between <code>call<\/code> and <code>delegatecall<\/code> in Solidity relates to the execution context:<\/p>\n<ul>\n<li><code>target.call(funcData)<\/code>:\n<ul>\n<li>the function reads\/modifies target contract's storage<\/li>\n<li><code>msg.sender<\/code> is the caller contract<\/li>\n<\/ul>\n<\/li>\n<li><code>target.delegatecall(funcData)<\/code>\n<ul>\n<li>the function reads\/modifies caller contract's storage<\/li>\n<li><code>msg.sender<\/code> is the original sender == caller contract's <code>msg.sender<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<pre class=\"line-numbers\"><code class=\"language-solidity\">\/\/ SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.24;\n\nimport \"forge-std\/Test.sol\";\n\ncontract Target {\n    address public owner;\n    uint256 public value;\n\n    function setOwnerAndValue(uint256 valueArg) public {\n        owner = msg.sender;\n        value = valueArg;\n    }\n}\n\ncontract Caller {\n    address public owner;\n    uint256 public value;\n\n    function callSetOwnerAndValue(address target, uint256 valueArg) public {\n        (bool success, ) = target.call(abi.encodeWithSignature(\"setOwnerAndValue(uint256)\", valueArg));\n        require(success, \"call failed\");\n    }\n\n    function delegatecallSetOwnerAndValue(address target, uint256 valueArg) public {\n        (bool success, ) = target.delegatecall(abi.encodeWithSignature(\"setOwnerAndValue(uint256)\", valueArg));\n        require(success, \"delegatecall failed\");\n    }\n}\n\ncontract MyTest is Test {\n    address sender = makeAddr(\"sender\");\n    Target target;\n    Caller caller;\n\n    function setUp() public {\n        target = new Target();\n        caller = new Caller();\n\n        assertEq(target.owner(), address(0));\n        assertEq(target.value(), 0);\n        assertEq(caller.owner(), address(0));\n        assertEq(caller.value(), 0);\n    }\n\n    function test_callSetOwnerAndValue() public {\n        vm.prank(sender);\n        caller.callSetOwnerAndValue(address(target), 100);\n\n        \/\/ call modifies target contract's state, and target contract's msg.sender is caller contract\n        assertEq(target.owner(), address(caller));\n        assertEq(target.value(), 100);\n\n        \/\/ caller contract's state didn't change\n        assertEq(caller.owner(), address(0));\n        assertEq(caller.value(), 0);\n    }\n\n    function test_delegatecallSetOwnerAndValue() public {\n        vm.prank(sender);\n        caller.delegatecallSetOwnerAndValue(address(target), 200);\n\n        \/\/ target contract's state didn't change\n        assertEq(target.owner(), address(0));\n        assertEq(target.value(), 0);\n\n        \/\/ delegatecall runs in the context of caller contract, so msg.sender is sender\n        assertEq(caller.owner(), sender);\n        assertEq(caller.value(), 200);\n    }\n}<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/medium.com\/0xmantle\/solidity-series-part-3-call-vs-delegatecall-8113b3c76855\">https:\/\/medium.com\/0xmantle\/solidity-series-part-3-call-vs-delegatecall-8113b3c76855<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>delegatecall runs in the context of the caller contract.<\/p>\n","protected":false},"author":1,"featured_media":919,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[137],"tags":[149,143],"class_list":["post-878","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blockchain","tag-evm","tag-solidity"],"_links":{"self":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/878","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/comments?post=878"}],"version-history":[{"count":0,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/878\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media\/919"}],"wp:attachment":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media?parent=878"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/categories?post=878"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/tags?post=878"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}