<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jad Jbara</title>
    <description>The latest articles on DEV Community by Jad Jbara (@jadjbara3-cpu).</description>
    <link>https://dev.to/jadjbara3-cpu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4130515%2F49ecb16e-db36-4079-a404-7560e7b1b113.png</url>
      <title>DEV Community: Jad Jbara</title>
      <link>https://dev.to/jadjbara3-cpu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jadjbara3-cpu"/>
    <language>en</language>
    <item>
      <title>I deployed a currency on Arc mainnet for 13 cents. Here is everything, including the numbers that do not flatter it.</title>
      <dc:creator>Jad Jbara</dc:creator>
      <pubDate>Thu, 17 Sep 2026 21:43:38 +0000</pubDate>
      <link>https://dev.to/jadjbara3-cpu/i-deployed-a-currency-on-arc-mainnet-for-13-cents-here-is-everything-including-the-numbers-that-4m4g</link>
      <guid>https://dev.to/jadjbara3-cpu/i-deployed-a-currency-on-arc-mainnet-for-13-cents-here-is-everything-including-the-numbers-that-4m4g</guid>
      <description>&lt;p&gt;Arc is Circle's USDC-native L1. I wanted to know what it actually takes to put a real token on it — not a testnet walkthrough, but mainnet, with a verified contract and a live market. So I did it and wrote down every step.&lt;/p&gt;

&lt;p&gt;Total cost from an empty wallet to a verified, indexed, tradeable token: &lt;strong&gt;about 11 cents&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What shipped
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Noor (NUR)&lt;/strong&gt; — an ERC-20 on Arc mainnet, chain ID 5042. Supply is fixed at 1,000,000,000 in the constructor, so &lt;code&gt;cap()&lt;/code&gt; equals &lt;code&gt;totalSupply()&lt;/code&gt; and &lt;code&gt;remainingMintable()&lt;/code&gt; returns &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Contract: &lt;code&gt;0x82c9411BBDdafF86F0Ee8E95275256AE136F8c1f&lt;/code&gt; — source verified as an &lt;strong&gt;exact match&lt;/strong&gt; (solc 0.8.28, evm cancun, optimizer 200 runs).&lt;/li&gt;
&lt;li&gt;A real &lt;strong&gt;Uniswap v2 pool&lt;/strong&gt;: &lt;code&gt;0xa8dC7Eba119949500F8e18fD086a0bF151095910&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;payment app&lt;/strong&gt; on GitHub Pages with no backend and no custody, reading balances and price straight from the chain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The real cost
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Contract deployment (1.82M gas at ~21 gwei)&lt;/td&gt;
&lt;td&gt;$0.088&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Circle CCTP bridge, Base to Arc&lt;/td&gt;
&lt;td&gt;$0.016&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One swap to trigger DEX indexing&lt;/td&gt;
&lt;td&gt;$0.006&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$0.11&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Getting USDC onto Arc was the awkward part. Arc has no faucet, so the USDC has to come from somewhere real. I bridged from Base with Circle CCTP V2 and used the Forwarding Service so Circle submitted the destination mint itself — which matters, because on Arc the gas token &lt;em&gt;is&lt;/em&gt; USDC and a fresh wallet has none.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six things that cost me hours
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. On Arc the gas token IS the bridged token, and they share one balance
&lt;/h3&gt;

&lt;p&gt;This one broke my bridge script on the first run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;depositForBurnWithHook reverted: "ERC20: transfer amount exceeds balance"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script read the USDC balance, sent an &lt;code&gt;approve&lt;/code&gt;, then tried to transfer &lt;em&gt;that same balance&lt;/em&gt;. But the approve consumed gas — and on Arc gas is paid in USDC, out of the very same balance. The number it read was already stale.&lt;/p&gt;

&lt;p&gt;The fix: re-read the balance &lt;em&gt;after&lt;/em&gt; the approve, estimate the burn transaction's gas, and hold that back before computing the amount.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gasUnits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;messenger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;depositForBurnWithHook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;estimateGas&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;feeData&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;srcProv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFeeData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gasWei&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gasUnits&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feeData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxFeePerGas&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reserve&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gasWei&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;_000n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// native 18dp -&amp;gt; USDC 6dp&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;burnAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;freshBalance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;reserve&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I only found it because I ran the whole bridge on testnet first. On mainnet it would have been the first attempt, with real money.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Aggregators index a pair only after its FIRST SWAP
&lt;/h3&gt;

&lt;p&gt;I created the pool, confirmed it on chain, and then could not find it anywhere. It was invisible on DexScreener and GeckoTerminal.&lt;/p&gt;

&lt;p&gt;DexScreener's own documentation is explicit: &lt;em&gt;"DexScreener automatically indexes every token that completes at least one swap on a supported decentralized exchange... Pool creation alone is not sufficient."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One 0.05 USDC swap fixed it, and both aggregators picked the pair up within the hour. Creating the pool and &lt;em&gt;opening&lt;/em&gt; the market are two different events.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;token0()&lt;/code&gt; returns a 32-byte padded address
&lt;/h3&gt;

&lt;p&gt;My payment app printed a price of &lt;code&gt;$9.6e+29&lt;/code&gt; and the reserves were swapped. The cause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;rpcCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PAIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x0dfe1681&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// 0x0000...00003600...0000&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usdcIsT0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;USDC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// always false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;token0()&lt;/code&gt; returns an ABI-encoded address, so it comes back left-padded to 32 bytes. Comparing it to a bare checksummed address silently fails — no revert, no warning, just inverted numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;t0raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;code&gt;explorer.arc.io&lt;/code&gt; sits behind Cloudflare, so verification must come from a browser
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;POST /api?module=contract&amp;amp;action=verifysourcecode&lt;/code&gt; works, but the parameters have to go in the &lt;strong&gt;query string&lt;/strong&gt; — a form body is ignored. And the URL-length limit means the standard-JSON compiler input (about 150 KB) gets a &lt;code&gt;414 Request-URI Too Large&lt;/code&gt; from Cloudflare.&lt;/p&gt;

&lt;p&gt;The working path is the Blockscout v2 endpoint, as &lt;code&gt;multipart/form-data&lt;/code&gt;, with the compiler input as a &lt;strong&gt;file part named &lt;code&gt;files&lt;/code&gt;&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /api/v2/smart-contracts/{address}/verification/via/standard-input
  compiler_version             v0.8.28+commit.7893614a
  license_type                 mit
  autodetect_constructor_args  true
  constructor_arguments        (empty)
  files                        the standard-json-input file, as an upload
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sending that JSON as a plain string field is rejected with a bare &lt;code&gt;400 Bad Request&lt;/code&gt; and no explanation.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. 20 gwei is a protocol floor on Arc, not a suggestion
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;maxFeePerGas&lt;/code&gt; below 20 gwei can leave a transaction pending indefinitely rather than failing quickly. I set &lt;code&gt;maxFeePerGas&lt;/code&gt; to twice the observed base fee and a 1 gwei tip.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Mainnet is open — verify that before you plan around credentials
&lt;/h3&gt;

&lt;p&gt;The docs mention a permissioned phase, so I tested the write path before funding anything: sign a transaction, send it, read the error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;-32003&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"insufficient funds for gas * price + value"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a normal EVM simulation failure, which means the node accepted and fully validated the transaction. No allowlist, no API key. Worth checking yourself rather than assuming.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers that do not flatter it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The pool holds &lt;strong&gt;$2.55&lt;/strong&gt;. Not a typo.&lt;/li&gt;
&lt;li&gt;A $1 buy moves the price about &lt;strong&gt;40%&lt;/strong&gt;. A $5 buy moves it about &lt;strong&gt;200%&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;$1,040&lt;/strong&gt; that aggregators print is arithmetic on those $2.55. It is not a valuation and nobody paid it.&lt;/li&gt;
&lt;li&gt;No utility, no community, no exchange listing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deploying a token is easy and costs cents. That was never the hard part, and any write-up that stops at "look, it deployed" is hiding the interesting question.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I deliberately did not do
&lt;/h2&gt;

&lt;p&gt;No volume bots. No wash trading between wallets I control. No paid boosts. No "buy before it moons".&lt;/p&gt;

&lt;p&gt;There is exactly one swap on the pool, it is 0.05 USDC, and it exists because DexScreener's documentation requires it to index the pair at all. It is labelled as an activation step in the repository, at the exact line where it happens.&lt;/p&gt;

&lt;p&gt;It would have been easy to make the numbers look better. That is precisely why I did not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repository, every script and every on-chain record: &lt;a href="https://github.com/jadjbara3-cpu/noor" rel="noopener noreferrer"&gt;https://github.com/jadjbara3-cpu/noor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Project page: &lt;a href="https://jadjbara3-cpu.github.io/noor/" rel="noopener noreferrer"&gt;https://jadjbara3-cpu.github.io/noor/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The pool, if you want to see what a $2.55 market looks like up close: &lt;a href="https://dexscreener.com/arc/0xa8dc7eba119949500f8e18fd086a0bf151095910" rel="noopener noreferrer"&gt;https://dexscreener.com/arc/0xa8dc7eba119949500f8e18fd086a0bf151095910&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy to go deeper on any of the six points above — they cost me a few hours each, and I would rather they cost you nothing.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>solidity</category>
    </item>
  </channel>
</rss>
