{"id":3175,"date":"2026-09-01T10:42:53","date_gmt":"2026-09-01T10:42:53","guid":{"rendered":"https:\/\/nownodes.io\/blog\/?p=3175"},"modified":"2026-09-01T10:42:54","modified_gmt":"2026-09-01T10:42:54","slug":"calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it","status":"publish","type":"post","link":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/","title":{"rendered":"Calldata vs. Memory vs. Storage in Solidity: What Each One Does and When to Use It"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Calldata is the read-only area where an external function&#8217;s arguments sit while a Solidity transaction runs \u2014 the raw call data attached to the transaction itself, and the cheapest of Solidity&#8217;s three data locations. It&#8217;s the one you should reach for by default whenever a function only needs to read its inputs. Memory holds temporary values for the duration of a single call, and storage is the only one of the three that survives after the transaction ends. Every variable in a Solidity contract lives in one of these three places, and getting Solidity calldata wrong for a given function is one of the most common ways contracts burn gas for no reason.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This isn&#8217;t a cosmetic choice. The same function, written with <code>memory<\/code> instead of <code>calldata<\/code> for its parameters, can cost noticeably more gas per call \u2014 money your users pay, every single time. Here&#8217;s the breakdown: what calldata actually is, why Solidity forces this choice on you at all, who needs to care, and the gas math that makes one keyword worth more than it looks.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-calldata-in-solidity\">What Is Calldata in Solidity?<\/h2>\n\n\n<p class=\"wp-block-paragraph\">Calldata is the raw byte data attached to a transaction or an external message call \u2014 the encoded function selector plus arguments that get sent along when one contract calls another, or when a user calls a contract directly. Solidity exposes that raw data as a data location: a keyword you can assign to function parameters so the compiler knows to read straight from calldata instead of copying it anywhere else.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Data location:<\/strong> in Solidity, one of three places \u2014 <code>storage<\/code>, <code>memory<\/code>, or <code>calldata<\/code> \u2014 where a reference-type variable (arrays, structs, strings, mappings) physically lives during execution. See the <a href=\"https:\/\/docs.soliditylang.org\/en\/latest\/types.html#data-location\" rel=\"nofollow noopener noreferrer\">official Solidity documentation on data locations<\/a> for the compiler&#8217;s exact rules.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s what that looks like in practice:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function isOwner(address&#91;] calldata whitelist, address user) external view returns (bool) {\n    for (uint i = 0; i &lt; whitelist.length; i++) {\n        if (whitelist&#91;i] == user) return true;\n    }\n    return false;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That <code>calldata<\/code> keyword tells the compiler this function never needs to modify <code>whitelist<\/code> \u2014 it only reads it. Nothing gets copied into memory first; the function reads directly from the transaction data itself.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"how-do-memory-and-storage-differ-from-calldata\">How Do Memory and Storage Differ From Calldata?<\/h2>\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-2-1024x683.png\" alt=\"\" class=\"wp-image-3176\" srcset=\"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-2-1024x683.png 1024w, https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-2-300x200.png 300w, https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-2-768x512.png 768w, https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-2.png 1536w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Storage is where a contract&#8217;s state variables actually live, written permanently to the blockchain and readable by anyone, forever, unless the contract itself overwrites it. Memory is a scratch space that exists only for the length of one external function call and gets wiped the moment that call finishes. Calldata sits apart from both: it isn&#8217;t written anywhere new at all, and it can&#8217;t be changed once the transaction starts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The practical distinction comes down to three questions: does the data need to persist after this call ends, does the function need to modify it, and where did the data come from in the first place.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Data location<\/th><th>Lifetime<\/th><th>Mutable?<\/th><th>Typical use<\/th><\/tr><\/thead><tbody><tr><td>Storage<\/td><td>Permanent, until overwritten<\/td><td>Yes<\/td><td>State variables, contract balances, mappings<\/td><\/tr><tr><td>Memory<\/td><td>One function call<\/td><td>Yes<\/td><td>Local working variables, values built during execution<\/td><\/tr><tr><td>Calldata<\/td><td>One function call, read-only<\/td><td>No<\/td><td>External function arguments that only get read<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">State variables default to storage automatically \u2014 you never write the keyword. Function parameters and local variables involving arrays, structs, or strings need an explicit location, and that&#8217;s the choice this whole guide is about.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"why-does-solidity-force-you-to-choose-a-data-location\">Why Does Solidity Force You to Choose a Data Location?<\/h2>\n\n\n<p class=\"wp-block-paragraph\">Solidity requires this because the Ethereum Virtual Machine treats these three areas as physically separate memory systems, each with its own cost and behavior, and the compiler can&#8217;t guess which one you meant for a complex type. A <code>uint256<\/code> fits in one stack slot, so the compiler handles it without asking. An array or a string doesn&#8217;t fit that way, so you tell the compiler exactly where it should read from or write to.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is critical: every operation on the Ethereum network costs gas, and gas has to be predictable before a transaction runs, or the network can&#8217;t safely price it. Storage writes touch permanent blockchain state shared by every node, which is why they&#8217;re the most expensive operation by far. Memory and calldata cost less because nothing about them needs to persist past the current call.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Skip the data location on a parameter that needs one, and the compiler stops you before deployment with a <code>TypeError: Data location must be 'memory' or 'calldata' for parameter in function, but none was given<\/code> \u2014 not a runtime failure, but a hard compile-time rule, exactly <a href=\"https:\/\/www.cyfrin.io\/blog\/fixing-data-location-must-be-memory-or-calldata\" rel=\"nofollow noopener noreferrer\">as Solidity&#8217;s error handling documents it<\/a>.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"who-actually-needs-to-think-about-this\">Who Actually Needs to Think About This?<\/h2>\n\n\n<p class=\"wp-block-paragraph\">Four groups run into this decision regularly, and for different reasons. Smart contract developers hit it on every function signature that takes an array, struct, or string \u2014 it&#8217;s not optional syntax, so understanding it isn&#8217;t optional either.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Gas optimization specialists and auditors look at data location choices specifically because they&#8217;re one of the highest-leverage, lowest-effort ways to cut a contract&#8217;s deployment and call costs. Teams building high-traffic contracts \u2014 DEX routers, NFT mints, anything called thousands of times a day \u2014 feel the cumulative gas difference directly in what their users pay. And anyone reviewing a <a href=\"https:\/\/nownodes.io\/blog\/top-smart-contract-auditing-firms\/\">smart contract audit<\/a> will see data location flagged constantly, since it&#8217;s a pattern auditors check almost mechanically.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"storage-vs-memory-vs-calldata-what-the-gas-actually-costs\">Storage vs. Memory vs. Calldata: What the Gas Actually Costs<\/h2>\n\n\n<p class=\"wp-block-paragraph\">This is where the choice stops being about syntax and starts mattering financially. Storage operations are priced through the EVM&#8217;s SSTORE and SLOAD opcodes, and the numbers aren&#8217;t close to calldata or memory.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Writing a storage variable from zero to a non-zero value costs 22,100 gas \u2014 20,000 for the write itself plus a 2,100 cold-access charge under <a href=\"https:\/\/eips.ethereum.org\/EIPS\/eip-2929\" rel=\"nofollow noopener noreferrer\">EIP-2929<\/a>, the Berlin-hardfork rule that raised the cost of a contract&#8217;s first storage access in a transaction. Michael Amadi and Jesse Raymond, the RareSkills researchers behind <em>The RareSkills Book of Solidity Gas Optimization<\/em>, put the scale of that plainly: &#8220;Initializing a storage variable is one of the most expensive operations a contract can do,&#8221; they write in their <a href=\"https:\/\/rareskills.io\/post\/gas-optimization\" rel=\"nofollow noopener noreferrer\">gas optimization guide<\/a> \u2014 and their most-repeated recommendation across 80-plus techniques is to avoid zero-to-non-zero storage writes wherever the logic allows it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Calldata is priced completely differently, per byte rather than per storage slot. <a href=\"https:\/\/eips.ethereum.org\/EIPS\/eip-2028\" rel=\"nofollow noopener noreferrer\">EIP-2028<\/a> dropped the cost of a non-zero calldata byte from 68 gas to 16 gas back in 2019, specifically to make data-heavy transactions and layer-2 rollups cheaper; a zero byte still costs 4 gas. Memory sits in between architecturally \u2014 reading or writing a memory word costs a small flat fee, plus a quadratic expansion cost that grows as a function uses more memory within a single call, which is why looping over a huge array copied into memory gets disproportionately expensive as the array grows.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Location<\/th><th>Typical gas cost<\/th><th>What drives the cost<\/th><\/tr><\/thead><tbody><tr><td>Storage (SSTORE, zero \u2192 non-zero)<\/td><td>22,100 gas<\/td><td>Permanent state change, cold access<\/td><\/tr><tr><td>Storage (SLOAD)<\/td><td>100\u20132,100 gas<\/td><td>Cold vs. warm access within a transaction<\/td><\/tr><tr><td>Calldata (per non-zero byte)<\/td><td>16 gas<\/td><td>Fixed per-byte transaction data cost<\/td><\/tr><tr><td>Memory<\/td><td>~3 gas + quadratic expansion<\/td><td>Grows non-linearly with total memory used<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The practical takeaway: if a function only reads its arguments, calldata almost always wins. It skips the copy into memory entirely, and the official Solidity docs are direct about this \u2014 the compiler documentation recommends using calldata &#8220;because it will avoid copies and also makes sure that the data cannot be modified&#8221; whenever a function doesn&#8217;t need to change the value.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"when-should-function-parameters-use-calldata-instead-of-memory\">When Should Function Parameters Use Calldata Instead of Memory?<\/h2>\n\n\n<p class=\"wp-block-paragraph\">The short version: use calldata for any external function parameter your code doesn&#8217;t modify, and reach for memory only when you actually need to change the value inside the function. Since Solidity 0.6.9, both keywords are legal on external, public, internal, and private functions alike, so there&#8217;s rarely a technical blocker \u2014 the choice mostly comes down to whether mutation is genuinely needed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">solidity<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Cheaper: read-only, external caller's data used as-is\nfunction sumArray(uint256&#91;] calldata values) external pure returns (uint256 total) {\n    for (uint i = 0; i &lt; values.length; i++) {\n        total += values&#91;i];\n    }\n}\n\n\/\/ Necessary: the function needs to modify the array before returning it\nfunction sortedCopy(uint256&#91;] memory values) public pure returns (uint256&#91;] memory) {\n    \/\/ sorting logic that reorders `values` in place\n    return values;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Internal functions called from within the same contract can also take storage references directly, avoiding a copy altogether when the goal is reading or updating state that&#8217;s already there. That&#8217;s a fourth pattern worth knowing, even though it&#8217;s not one of the three data locations for arguments in the strictest sense \u2014 it&#8217;s storage, just accessed by reference instead of by value.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"why-doesnt-solidity-constructor-calldata-exist\">Why Doesn&#8217;t Solidity Constructor Calldata Exist?<\/h2>\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-3-1024x683.png\" alt=\"\" class=\"wp-image-3178\" srcset=\"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-3-1024x683.png 1024w, https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-3-300x200.png 300w, https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-3-768x512.png 768w, https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/image-3.png 1536w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the part that catches people off guard: Solidity constructor calldata parameters aren&#8217;t allowed at all. Try <code>constructor(string calldata _name)<\/code> and the compiler rejects it \u2014 constructors only accept <code>memory<\/code> for arrays, structs, and strings, never <code>calldata<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The reason is architectural, not arbitrary. A normal function call has its arguments encoded directly in the transaction&#8217;s calldata, which the EVM reads with the <code>CALLDATALOAD<\/code> opcode. Contract creation works differently: constructor arguments get ABI-encoded and appended to the very end of the deployment bytecode itself, after the contract&#8217;s runtime code. The EVM&#8217;s init code then calculates the argument length using <code>CODESIZE<\/code> and pulls the data out with <code>CODECOPY<\/code>, <a href=\"https:\/\/rareskills.io\/post\/ethereum-contract-creation-code\" rel=\"nofollow noopener noreferrer\">not <code>CALLDATACOPY<\/code><\/a> \u2014 because during deployment, there&#8217;s no separate calldata channel the way there is for a message call to an already-deployed contract.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s a real trade-off, not just trivia. Calldata results in cheaper transactions for the user, but that saving genuinely isn&#8217;t available at deployment time \u2014 constructor arguments always pay the memory-copy cost, no matter how the code is written.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"common-mistakes-that-waste-gas-on-data-locations\">Common Mistakes That Waste Gas on Data Locations<\/h2>\n\n\n<p class=\"wp-block-paragraph\">A handful of patterns account for most of the avoidable gas waste here. Copying a <code>calldata<\/code> array into <code>memory<\/code> just to pass it to another internal function that could accept <code>calldata<\/code> directly is one of the most frequent \u2014 it pays for a copy the code never needed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Using <code>memory<\/code> on an external function&#8217;s array or string parameter out of habit, when the body never modifies it, is another. So is reading the same storage variable repeatedly inside a loop instead of caching it once locally \u2014 each <code>SLOAD<\/code> gets billed separately, even against the same slot. None of these mistakes break a contract; they just mean users pay more than the logic requires, which is exactly the kind of gap an <a href=\"https:\/\/nownodes.io\/blog\/top-smart-contract-auditing-firms\/\">independent security and gas audit<\/a> is built to catch before mainnet.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"how-do-you-check-gas-costs-before-you-deploy\">How Do You Check Gas Costs Before You Deploy?<\/h2>\n\n\n<p class=\"wp-block-paragraph\">The only reliable way to know whether a data location choice actually saved gas is to test it against real network state before shipping. <a href=\"https:\/\/nownodes.io\/blog\/how-to-simulate-a-transaction-on-ethereum\/\">Simulating a transaction<\/a> with <code>eth_call<\/code> or a full <code>debug_traceCall<\/code> shows the exact gas a function consumes, without spending anything or waiting for a block.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That check depends on RPC access to current chain state. NOWNodes, for instance, offers Ethereum RPC and Debug\/Trace API access across mainnet and testnets, so a developer can compare calldata against memory, or one storage layout against another, against live state without running a self-hosted debug-enabled node.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The same read-only principle shows up one layer up the stack, too. <a href=\"https:\/\/nownodes.io\/blog\/what-are-meta-transactions-erc-2771\/\">Meta-transaction relayers<\/a> append the real sender&#8217;s address to the end of a forwarded call&#8217;s calldata specifically because calldata is cheap to extend and easy for a receiving contract to parse \u2014 the same cost profile that makes it the right default for ordinary read-only function arguments.<\/p>\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n<p class=\"wp-block-paragraph\">Calldata, memory, and storage aren&#8217;t interchangeable syntax \u2014 they&#8217;re three different places with three different lifetimes and three very different price tags. Storage is for what genuinely needs to survive on-chain. Memory is for values a function builds and discards within one call. Calldata is for external arguments a function only needs to read, and it should be the default whenever nothing forces a copy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Get comfortable with which is which, and one keyword choice on a function signature stops being a syntax detail and starts being a real, measurable saving passed on to whoever calls that function. The constructor exception is worth remembering precisely because it&#8217;s the one place that saving isn&#8217;t available \u2014 a small architectural quirk that makes more sense once you know what <code>CODECOPY<\/code> is doing behind it.<\/p>\n\n\n<h3 class=\"wp-block-heading\" id=\"faq\">FAQ<\/h3>\n\n<h3 class=\"wp-block-heading\" id=\"can-you-change-a-calldata-variable-inside-a-function\">Can You Change a Calldata Variable Inside a Function?<\/h3>\n\n\n<p class=\"wp-block-paragraph\">No. Calldata is explicitly non-modifiable \u2014 any attempt to write to a calldata array or struct fails at compile time. If a function needs to alter the data, it has to copy the relevant part into memory first.<\/p>\n\n\n<h3 class=\"wp-block-heading\" id=\"is-calldata-only-available-for-external-functions\">Is Calldata Only Available for External Functions?<\/h3>\n\n\n<p class=\"wp-block-paragraph\">No, not since Solidity 0.6.9. Before that release, calldata was restricted to external function parameters; today, both memory and calldata are legal data locations on external, public, internal, and private functions alike.<\/p>\n\n\n<h3 class=\"wp-block-heading\" id=\"does-using-calldata-instead-of-memory-ever-make-a-function-slower\">Does Using Calldata Instead of Memory Ever Make a Function Slower?<\/h3>\n\n\n<p class=\"wp-block-paragraph\">No \u2014 calldata access is at least as fast as memory access at the EVM level, and it skips a copy operation memory requires. The gas savings and any performance difference both point the same direction, toward calldata for read-only data.<\/p>\n\n\n<h3 class=\"wp-block-heading\" id=\"what-happens-if-you-try-to-return-a-calldata-variable-from-a-function\">What Happens If You Try to Return a Calldata Variable From a Function?<\/h3>\n\n\n<p class=\"wp-block-paragraph\">It works, since returning a value doesn&#8217;t modify it \u2014 a function can accept a calldata array and return it, or a slice of it, without ever copying it into memory first.<\/p>\n\n\n<h3 class=\"wp-block-heading\" id=\"do-public-functions-default-to-memory-or-calldata\">Do Public Functions Default to Memory or Calldata?<\/h3>\n\n\n<p class=\"wp-block-paragraph\">Neither is chosen automatically. Every reference-type parameter on a public or external function needs an explicit <code>memory<\/code> or <code>calldata<\/code> keyword; leaving it out is a compile error, not a default.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Calldata is the read-only area where an external function&#8217;s arguments sit while a Solidity transaction runs \u2014 the raw call data attached to the transaction itself, and the cheapest of Solidity&#8217;s three data locations. It&#8217;s the one you should reach for by default whenever a function only needs to read its inputs. Memory holds temporary [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":3177,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_eb_attr":"","_lmt_disableupdate":"","_lmt_disable":"","_monsterinsights_skip_tracking":false,"footnotes":""},"categories":[102],"tags":[],"class_list":["post-3175","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev-report"],"blocksy_meta":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Solidity Data Locations Explained: Calldata, Memory, Storage<\/title>\n<meta name=\"description\" content=\"See how calldata, memory, and storage differ in Solidity \u2014 with real gas numbers, code examples, and the one rule constructors can&#039;t follow.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Solidity Data Locations Explained: Calldata, Memory, Storage\" \/>\n<meta property=\"og:description\" content=\"See how calldata, memory, and storage differ in Solidity \u2014 with real gas numbers, code examples, and the one rule constructors can&#039;t follow.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/\" \/>\n<meta property=\"og:site_name\" content=\"NOWNodes Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-01T10:42:53+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-01T10:42:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/nodes_1-8.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2400\" \/>\n\t<meta property=\"og:image:height\" content=\"1200\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"\u0410nastasia\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nownodes\" \/>\n<meta name=\"twitter:site\" content=\"@nownodes\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u0410nastasia\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/\"},\"author\":{\"name\":\"\u0410nastasia\",\"@id\":\"https:\/\/nownodes.io\/blog\/#\/schema\/person\/0890ec68e813adecb93c18ee00e1e7a8\"},\"headline\":\"Calldata vs. Memory vs. Storage in Solidity: What Each One Does and When to Use It\",\"datePublished\":\"2026-09-01T10:42:53+00:00\",\"dateModified\":\"2026-09-01T10:42:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/\"},\"wordCount\":2151,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/nownodes.io\/blog\/#organization\"},\"articleSection\":[\"Dev Report\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/\",\"url\":\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/\",\"name\":\"Solidity Data Locations Explained: Calldata, Memory, Storage\",\"isPartOf\":{\"@id\":\"https:\/\/nownodes.io\/blog\/#website\"},\"datePublished\":\"2026-09-01T10:42:53+00:00\",\"dateModified\":\"2026-09-01T10:42:54+00:00\",\"description\":\"See how calldata, memory, and storage differ in Solidity \u2014 with real gas numbers, code examples, and the one rule constructors can't follow.\",\"breadcrumb\":{\"@id\":\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Blog\",\"item\":\"https:\/\/nownodes.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Dev Report\",\"item\":\"https:\/\/nownodes.io\/blog\/category\/dev-report\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Calldata vs. Memory vs. Storage in Solidity: What Each One Does and When to Use It\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/nownodes.io\/blog\/#website\",\"url\":\"https:\/\/nownodes.io\/blog\/\",\"name\":\"NOWNodes Blog\",\"description\":\"Your first-to-go source of development guides, web3 analytics and most recent news about NOWNodes\",\"publisher\":{\"@id\":\"https:\/\/nownodes.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/nownodes.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/nownodes.io\/blog\/#organization\",\"name\":\"NOWNodes Blog\",\"url\":\"https:\/\/nownodes.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/nownodes.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2024\/02\/cropped-New-Logo-NN.png\",\"contentUrl\":\"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2024\/02\/cropped-New-Logo-NN.png\",\"width\":1164,\"height\":1164,\"caption\":\"NOWNodes Blog\"},\"image\":{\"@id\":\"https:\/\/nownodes.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/twitter.com\/nownodes\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/nownodes.io\/blog\/#\/schema\/person\/0890ec68e813adecb93c18ee00e1e7a8\",\"name\":\"\u0410nastasia\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/nownodes.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/1de24ab8dcdd7ec30f6adaf78b56bc1eda421f87575b7e103c8fc3fc4420e833?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/1de24ab8dcdd7ec30f6adaf78b56bc1eda421f87575b7e103c8fc3fc4420e833?s=96&d=mm&r=g\",\"caption\":\"\u0410nastasia\"},\"url\":\"https:\/\/nownodes.io\/blog\/author\/nasty-nownodes\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Solidity Data Locations Explained: Calldata, Memory, Storage","description":"See how calldata, memory, and storage differ in Solidity \u2014 with real gas numbers, code examples, and the one rule constructors can't follow.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/","og_locale":"en_US","og_type":"article","og_title":"Solidity Data Locations Explained: Calldata, Memory, Storage","og_description":"See how calldata, memory, and storage differ in Solidity \u2014 with real gas numbers, code examples, and the one rule constructors can't follow.","og_url":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/","og_site_name":"NOWNodes Blog","article_published_time":"2026-09-01T10:42:53+00:00","article_modified_time":"2026-09-01T10:42:54+00:00","og_image":[{"width":2400,"height":1200,"url":"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2026\/09\/nodes_1-8.png","type":"image\/png"}],"author":"\u0410nastasia","twitter_card":"summary_large_image","twitter_creator":"@nownodes","twitter_site":"@nownodes","twitter_misc":{"Written by":"\u0410nastasia","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/#article","isPartOf":{"@id":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/"},"author":{"name":"\u0410nastasia","@id":"https:\/\/nownodes.io\/blog\/#\/schema\/person\/0890ec68e813adecb93c18ee00e1e7a8"},"headline":"Calldata vs. Memory vs. Storage in Solidity: What Each One Does and When to Use It","datePublished":"2026-09-01T10:42:53+00:00","dateModified":"2026-09-01T10:42:54+00:00","mainEntityOfPage":{"@id":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/"},"wordCount":2151,"commentCount":0,"publisher":{"@id":"https:\/\/nownodes.io\/blog\/#organization"},"articleSection":["Dev Report"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/","url":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/","name":"Solidity Data Locations Explained: Calldata, Memory, Storage","isPartOf":{"@id":"https:\/\/nownodes.io\/blog\/#website"},"datePublished":"2026-09-01T10:42:53+00:00","dateModified":"2026-09-01T10:42:54+00:00","description":"See how calldata, memory, and storage differ in Solidity \u2014 with real gas numbers, code examples, and the one rule constructors can't follow.","breadcrumb":{"@id":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/nownodes.io\/blog\/calldata-vs-memory-vs-storage-in-solidity-what-each-one-does-and-when-to-use-it\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Blog","item":"https:\/\/nownodes.io\/blog"},{"@type":"ListItem","position":2,"name":"Dev Report","item":"https:\/\/nownodes.io\/blog\/category\/dev-report"},{"@type":"ListItem","position":3,"name":"Calldata vs. Memory vs. Storage in Solidity: What Each One Does and When to Use It"}]},{"@type":"WebSite","@id":"https:\/\/nownodes.io\/blog\/#website","url":"https:\/\/nownodes.io\/blog\/","name":"NOWNodes Blog","description":"Your first-to-go source of development guides, web3 analytics and most recent news about NOWNodes","publisher":{"@id":"https:\/\/nownodes.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/nownodes.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/nownodes.io\/blog\/#organization","name":"NOWNodes Blog","url":"https:\/\/nownodes.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/nownodes.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2024\/02\/cropped-New-Logo-NN.png","contentUrl":"https:\/\/nownodes.io\/blog\/wp-content\/uploads\/2024\/02\/cropped-New-Logo-NN.png","width":1164,"height":1164,"caption":"NOWNodes Blog"},"image":{"@id":"https:\/\/nownodes.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/twitter.com\/nownodes"]},{"@type":"Person","@id":"https:\/\/nownodes.io\/blog\/#\/schema\/person\/0890ec68e813adecb93c18ee00e1e7a8","name":"\u0410nastasia","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/nownodes.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/1de24ab8dcdd7ec30f6adaf78b56bc1eda421f87575b7e103c8fc3fc4420e833?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1de24ab8dcdd7ec30f6adaf78b56bc1eda421f87575b7e103c8fc3fc4420e833?s=96&d=mm&r=g","caption":"\u0410nastasia"},"url":"https:\/\/nownodes.io\/blog\/author\/nasty-nownodes"}]}},"modified_by":"\u0410nastasia","_links":{"self":[{"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/posts\/3175","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/comments?post=3175"}],"version-history":[{"count":1,"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/posts\/3175\/revisions"}],"predecessor-version":[{"id":3179,"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/posts\/3175\/revisions\/3179"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/media\/3177"}],"wp:attachment":[{"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/media?parent=3175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/categories?post=3175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nownodes.io\/blog\/wp-json\/wp\/v2\/tags?post=3175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}