<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>William Entriken Blog</title>
    <description>Essays by William Entriken</description>
    <link>https://blog.phor.net/</link>
    <atom:link href="https://blog.phor.net/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 12 Jul 2026 16:44:11 +0000</pubDate>
    <lastBuildDate>Sun, 12 Jul 2026 16:44:11 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>NFT/RWA资源如何帮助国资和企业实现项目？</title>
        <description>&lt;p&gt;研究国资现在情况和RWA现代回机会。对比西方NFT/RWA玩法和中国市场应用。&lt;/p&gt;

&lt;h2 id=&quot;作家简介&quot;&gt;作家简介&lt;/h2&gt;

&lt;p&gt;你好，我是William Entriken（安其文）。我认为NFT和雷斯的技术可以带来更顺利、更可靠政府和企业操作。我曾参与多个政府和私立企业，帮助设计项目并提供指导。我没有可卖的平台也没有手下的员工。哪里需要我聊天、演讲或咨询，我就去哪里。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;NFT之父。2017年作为NFT文章（ERC-721）主作者。&lt;/li&gt;
  &lt;li&gt;2018初实现技术，工程师合作。&lt;/li&gt;
  &lt;li&gt;2018年初在上海和美国演讲 NFT 是什么以及如何应用。（NFT 概念曾进入上海“十四五”规划。）&lt;/li&gt;
  &lt;li&gt;2018年至今，我与政府和私立公司合作，用 NFT 帮助企业实现项目。（不涉及比特币或发币类项目。）&lt;/li&gt;
  &lt;li&gt;2019–2020和西欧洲政府分析区块链的应用前景。&lt;/li&gt;
  &lt;li&gt;2020–2023年与美国政府合作，研究如何应用区块链技术，并提供法律分析支持。&lt;/li&gt;
  &lt;li&gt;2021–2024年与东欧（爱沙尼亚）立法部门交流如何利用欧盟区块链法律框架。&lt;/li&gt;
  &lt;li&gt;商业背景：本科电子与计算机工程，硕士金融与国际贸易。2006年在谷歌工作，2008年从事通信芯片领域，此后为科技公司提供发展和创业咨询。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;国内报道&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.chinadaily.com.cn/a/202105/07/WS6094db49a31024ad0babc83e_2.html&quot;&gt;China Daily 摆到&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20210619084916/https://www.jinse.com/news/blockchain/357441.html&quot;&gt;金色 报道&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.hplpb.com.cn/article/doi/10.11884/HPLPB201931.190132&quot;&gt;HPLPB 报道&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.c114.com.cn/expo/15/a1050187.html&quot;&gt;C114 报道&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cloud.tencent.com.cn/developer/article/1047352&quot;&gt;腾讯 报道&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.lucaijing.com.cn/yc/yyz/3227.html&quot;&gt;鹿财经网 报道&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;百度百科&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;国际政府报道（&lt;a href=&quot;https://phor.net/speaking#speaking&quot;&gt;英文&lt;/a&gt;，外国网）&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8301.pdf&quot;&gt;美国国家标准与技术研究院&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=cQ1QOLGJPIw&amp;amp;feature=youtu.be&quot;&gt;采访爱沙尼亚科技部长&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://x.com/bledstratforum/status/1039482666024947712&quot;&gt;斯洛文尼亚欧盟政府演讲&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=7LoMoqltRzM&quot;&gt;和东北欧政府如何禁止区块链洗钱&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/William_Entriken&quot;&gt;Wikipedia William Entriken&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://scholar.google.com/citations?user=4rGYvTgAAAAJ&amp;amp;hl=en&quot;&gt;Google Scholar 研究单&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://phor.net/speaking#speaking&quot;&gt;更多&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;国资问题&quot;&gt;国资问题&lt;/h2&gt;

&lt;p&gt;国资的作用就是按照中央党国务院和省政府的计划和需求设计项目的机会。有了项目再和各个政府商量如何符合项目资本的需求。最终要负责项目成功。国资会参与多轮的项目，也会连续和各个政府和伙伴合作。&lt;/p&gt;

&lt;p&gt;每一次项目成功，下一轮更顺利了。项目和五年计划吻合无缝对接。国资信任为重要。&lt;/p&gt;

&lt;p&gt;我们以下举个例子，分析相关刚出的15五年计划。也可以多加雷斯细节。&lt;/p&gt;

&lt;h3 id=&quot;例如项目内蒙古ai算力城&quot;&gt;例如项目：内蒙古AI算力城&lt;/h3&gt;

&lt;p&gt;按照15五年计划建立一个国际级算力中心（10亿瓦级）。&lt;/p&gt;

&lt;!-- 照片来自 https://lcj.yn.gov.cn/html/2022/guonei_0812/66779.html --&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2026-07-03-nft-guozi.webp&quot; alt=&quot;建立计算城&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们先分析在内蒙古该项目的需求：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;🟢 地面&lt;/li&gt;
  &lt;li&gt;🟢 矿场的煤炭&lt;/li&gt;
  &lt;li&gt;🟢 发电厂（10亿瓦级）&lt;/li&gt;
  &lt;li&gt;🟢 算力城外壳设计&lt;/li&gt;
  &lt;li&gt;🟢 算力城外壳建立（包电力、电池、散热，外网）&lt;/li&gt;
  &lt;li&gt;🟢 算力城内网络（服务器与服务器）&lt;/li&gt;
  &lt;li&gt;🟠 了解应用需求&lt;/li&gt;
  &lt;li&gt;🟠 服务器&lt;/li&gt;
  &lt;li&gt;🟠 AI芯片&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在国外类似资本需求大约500亿美元（房地产、建设、发电厂、服务器、芯片）。在国内估计会便宜一些。但是实现该项目会需要国资和省、市政府和其他方大力支持。&lt;/p&gt;

&lt;p&gt;ℹ️ 关心点：以上的资本需求大大大量在于&lt;strong&gt;🟠服务器&lt;/strong&gt;和&lt;strong&gt;🟠AI芯片&lt;/strong&gt;。&lt;/p&gt;

&lt;h2 id=&quot;国资和私资对比&quot;&gt;国资和私资对比&lt;/h2&gt;

&lt;p&gt;我已经分析过如何在蒙古建立算力中心。外蒙私立、内蒙私立和内蒙国资项目都不同。以下对比项目&lt;strong&gt;基础&lt;/strong&gt;：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;外蒙私立&lt;/th&gt;
      &lt;th&gt;内蒙私立&lt;/th&gt;
      &lt;th&gt;内蒙国资&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;🟢 地面&lt;/td&gt;
      &lt;td&gt;❌ 不能保证&lt;/td&gt;
      &lt;td&gt;❌ 不能保证&lt;/td&gt;
      &lt;td&gt;✅ 可保证&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;🟢 矿场的煤炭&lt;/td&gt;
      &lt;td&gt;✅ 可以买&lt;/td&gt;
      &lt;td&gt;❌ 不能保证&lt;/td&gt;
      &lt;td&gt;✅ 可保证&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;🟢 发电厂&lt;/td&gt;
      &lt;td&gt;❌ 不能保证&lt;/td&gt;
      &lt;td&gt;❌ 不能保证&lt;/td&gt;
      &lt;td&gt;✅ 可保证&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;🟢 算力城外壳设计&lt;/td&gt;
      &lt;td&gt;✅ 可以做&lt;/td&gt;
      &lt;td&gt;❌ 不能保证&lt;/td&gt;
      &lt;td&gt;✅ 可保证&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;🟢 算力城外壳建立（包电力、电池、散热，外网）&lt;/td&gt;
      &lt;td&gt;✅ 可以做&lt;/td&gt;
      &lt;td&gt;❌ 不能保证&lt;/td&gt;
      &lt;td&gt;✅ 可保证&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;🟢 算力城内网络&lt;/td&gt;
      &lt;td&gt;✅ 可以做&lt;/td&gt;
      &lt;td&gt;✅ 可以做&lt;/td&gt;
      &lt;td&gt;✅ 可保证&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;剩下的算力部分更难说：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;外蒙私立&lt;/th&gt;
      &lt;th&gt;内蒙私立&lt;/th&gt;
      &lt;th&gt;内蒙国资&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;🟠 了解应用需求&lt;/td&gt;
      &lt;td&gt;✅ 懂得多&lt;/td&gt;
      &lt;td&gt;✅ 懂得多&lt;/td&gt;
      &lt;td&gt;❓ 可问企业&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;🟠 服务器&lt;/td&gt;
      &lt;td&gt;✅ 可以买&lt;/td&gt;
      &lt;td&gt;✅ 可以买&lt;/td&gt;
      &lt;td&gt;✅ 用国内的&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;🟠 AI芯片&lt;/td&gt;
      &lt;td&gt;✅ 用国外的&lt;/td&gt;
      &lt;td&gt;❓&lt;/td&gt;
      &lt;td&gt;✅ 用国内的&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;项目的&lt;strong&gt;基础&lt;/strong&gt;国资十分可以做得到。&lt;strong&gt;私立资本无法保证项目实现。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;国资自己买&lt;strong&gt;服务器&lt;/strong&gt;和&lt;strong&gt;AI芯片&lt;/strong&gt;有可能买错款。还有这一部分是大大大量资本需求。&lt;/p&gt;

&lt;p&gt;到这一点我们可以分析NFT/RWA资源如何帮助国资实现项目难点，还有西方的NFT/RWA和中国内应怎么不一样。&lt;/p&gt;

&lt;h2 id=&quot;如何用nftrwa资源帮助项目&quot;&gt;如何用NFT/RWA资源帮助项目&lt;/h2&gt;

&lt;p&gt;目前的困难是：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;最终算力城要符合企业算力需求。&lt;/li&gt;
  &lt;li&gt;资本参与方需要确信项目能够顺利实现。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;服务器&lt;/strong&gt;和&lt;strong&gt;AI芯片&lt;/strong&gt;需求可能比国资提出过类似的项目更大。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;还有不要忘记国资强项：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;只有国资能保证各个省市政府的合作。&lt;/li&gt;
  &lt;li&gt;国资获得面积、发电证和别的证都不紧。&lt;/li&gt;
  &lt;li&gt;AI大算力是15五年计划的目标企业。&lt;/li&gt;
  &lt;li&gt;国资能带来N多企业方介绍新的企业方式。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RWA资源可以带来一个合适的资本方式。可能更适合该项目。我们先对比几种资本方式：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;投资&lt;/th&gt;
      &lt;th&gt;贷款/债券&lt;/th&gt;
      &lt;th&gt;⭐️ 质押&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;项目成功后分红&lt;/td&gt;
      &lt;td&gt;项目还在发利息&lt;/td&gt;
      &lt;td&gt;项目实现后有权合作&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;我们可以想象算力城是一个多横多竖的格子。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;1号位置&lt;/th&gt;
      &lt;th&gt;2号位置&lt;/th&gt;
      &lt;th&gt;3号位置&lt;/th&gt;
      &lt;th&gt;4号位置&lt;/th&gt;
      &lt;th&gt;5号位置&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;。。。。。。&lt;/td&gt;
      &lt;td&gt;。。。。。。&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;每一个格子有一定的面积、一定的电力容量、一定的内外网、一定的散热限制。&lt;/p&gt;

&lt;p&gt;如果国资已经通过所有的面积、发电、类似的证那就可以拍卖质押券。项目建立好之后谁持有该券，就有权利入驻。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐️ 质押方提供自己的服务器和 AI 芯片。质押方入驻后仍需支付房租和电费。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这些质押券可按市场价格拍卖给企业方。&lt;/p&gt;

&lt;p&gt;这种资本方式可以带来大量早期的资本。也会减少国资的风险。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐️ 通过质押资本，参与方为什么最相信项目会实现？因为政府方实现之后政府方还可以赚很多房租和电费。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;通过 NFT/RWA 技术，质押方持有的权益仍有流动性。在合规的国产区块链上（如果政府允许），A 方可以在二手市场持有的位置。A 方和 B 方也可以交换位置（AI 服务器对距离和位置非常敏感）。&lt;/p&gt;

&lt;p&gt;西方的NFT/RWA和中国内应技术怎么不一样？&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;西方RWA资源&lt;/th&gt;
      &lt;th&gt;中国内资源&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;NFT可以金融化&lt;/td&gt;
      &lt;td&gt;政府可以禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;匿名方可以获得NFT&lt;/td&gt;
      &lt;td&gt;过链可禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;可用去中心化金融&lt;/td&gt;
      &lt;td&gt;可绑定人民币交易&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;除了技术意外，私立公司更喜欢高风险项目。他们不依赖政府贷款和质押模式。他们会到各个国家参与证券交易。国资的风险偏好不同，因此质押方式可能更适合。&lt;/p&gt;

&lt;h2 id=&quot;下一步&quot;&gt;下一步&lt;/h2&gt;

&lt;p&gt;请与我联系。我会帮你：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;分析如何利用新经济模式提高你的项目成功率。&lt;/li&gt;
  &lt;li&gt;推荐在国内怎么用国产的区块链（或者非区块链技术）实现新经济模式。&lt;/li&gt;
  &lt;li&gt;利用我10多年的经验来分析你的项目和资本方式。&lt;/li&gt;
  &lt;li&gt;就像我和美国和欧洲政府合作一样，和中国政府分析合适的法律和市场规则。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;如果你的项目成功了我希望改天我可以再来上海和国资演讲如何新技术帮助企业应用。&lt;/p&gt;
</description>
        <pubDate>Fri, 03 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/nft-guozi</link>
        <guid isPermaLink="true">https://blog.phor.net/nft-guozi</guid>
        
        <category>blockchain</category>
        
        
      </item>
    
      <item>
        <title>The future of web3 is centralization</title>
        <description>&lt;p&gt;A friend asked me a sharp question after my Google talk:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“How will the world ever move from the custodial world we live in (banks, trading accounts, etc.) to a world where I have a single private key and really ‘own’ these NFTs?&lt;/p&gt;

  &lt;p&gt;Smart contracts and even soulbound NFTs assume we’ll all suddenly guard our private keys with our lives, only to be forced to follow every on-chain rule, fee, and restriction. Instead, I can just trust Coinbase (or whoever wins). I get convenience, the ability to sell to anyone, and I can skirt blockchain rules. Help me understand this.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s my perspective:&lt;/p&gt;

&lt;p&gt;&lt;mark&gt;Business processes don’t change. Only the methods change.&lt;/mark&gt;&lt;/p&gt;

&lt;p&gt;For thousands of years, humans have happily owned assets &lt;em&gt;beneficially&lt;/em&gt; while handing custody to someone else. We do it with money in banks, physical gold in vaults, real estate protection through government, stocks through brokers, art in galleries or museums. The vast majority of marketable assets with defined ownership are held by a separate custodian. (And perhaps even all valuable assets.)&lt;/p&gt;

&lt;p&gt;When you give custody to another party, you lose direct control, but you gain offsetting benefits: convenience, security services, financialization, insurability, dispute resolution, and more.&lt;/p&gt;

&lt;p&gt;Crypto is no different.&lt;/p&gt;

&lt;p&gt;In 2018 we saw heavy self-custody for two reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Early adopters are a special group. They enjoy the risk, the ideology and the new value propositions.&lt;/li&gt;
  &lt;li&gt;Many mainstream users who just arrived simply don’t know any better yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But humans as a whole have &lt;em&gt;never&lt;/em&gt; valued direct, personal custody of assets as highly as the “not your keys, not your coins” crowd hopes.&lt;/p&gt;

&lt;p&gt;The end result? Long term, nearly everyone will opt for custodial holding.&lt;/p&gt;

&lt;p&gt;They will happily let Coinbase, a future super-app, or some trusted institution hold the keys while they enjoy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No need to guard a private key with their life&lt;/li&gt;
  &lt;li&gt;Easy recovery if something goes wrong&lt;/li&gt;
  &lt;li&gt;Lower friction for everyday use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Self-custody will remain important for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;High-value operational “cold” holdings&lt;/li&gt;
  &lt;li&gt;People with high risk tolerance or strong ideological reasons&lt;/li&gt;
  &lt;li&gt;Specific use cases where trust minimization is worth the hassle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expecting the entire world to suddenly treat a 12-word seed phrase like their most precious physical possession was always unrealistic.&lt;/p&gt;
</description>
        <pubDate>Thu, 11 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/self-custody</link>
        <guid isPermaLink="true">https://blog.phor.net/self-custody</guid>
        
        <category>blockchain</category>
        
        
      </item>
    
      <item>
        <title>Notary pairs: immutable, mutual timestamping service for business relationships</title>
        <description>&lt;p&gt;You created a document today.&lt;/p&gt;

&lt;p&gt;When you deliver that to your business peer, you want confirmation that they received it and when. This includes emails, electronic document interchange and other business processes.&lt;/p&gt;

&lt;p&gt;One solution is to ensure that all business processes go through email, and that read receipts are always on. And that you check the receipts.&lt;/p&gt;

&lt;p&gt;Another extension of this technique is “notary pairs”. This approach applies to more kinds of data/processes and borrows from blockchain and &lt;a href=&quot;https://github.com/fulldecent/versioned_database_template&quot;&gt;versioned database template&lt;/a&gt; concepts.&lt;/p&gt;

&lt;h2 id=&quot;what-is-a-notary-pair&quot;&gt;What is a notary pair&lt;/h2&gt;

&lt;p&gt;A notary pair is a mutual, ongoing, connection established between two entities that notarizes documents. These will typically be used by businesses.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart LR
    A[Business A notary] &amp;lt;--&amp;gt; B[Business B notary]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They are synchronized and create an immutable ledger of document receipts.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;sequenceDiagram
    Business A notary-&amp;gt;&amp;gt;Business B notary: Receipt 1
    Business B notary-&amp;gt;&amp;gt;Business A notary: Receipt 2
    Business A notary-&amp;gt;&amp;gt;Business B notary: Receipt 3
    Business B notary-&amp;gt;&amp;gt;Business A notary: Receipt 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each entry contains exactly:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Incrementing serial number&lt;/strong&gt;, e.g. 1, 2, 3, …&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Timestamp&lt;/strong&gt;, also strictly increasing&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Prior entry hash&lt;/strong&gt;, a succinct calculated summary from the prior entry&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Payload&lt;/strong&gt;, typically a hash of some file or business record&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Signature&lt;/strong&gt;, of of the notary making the entry&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;(Optional) pentultimate signing key and new signing key&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is managed by an agent run in each entity’s system.&lt;/p&gt;

&lt;h2 id=&quot;zig-zag-etiquette&quot;&gt;Zig-zag etiquette&lt;/h2&gt;

&lt;p&gt;This system is designed as a zig-zag protocol where odd-numbered entries are from one side and even-numbered ones are from the other. If a participant wants to send a payload but it made the last turn (i.e. not its turn), then it politely asks the counterparty to create a empty-payload message. And then the microphone passes back.&lt;/p&gt;

&lt;p&gt;Each notary enforces the rules and will not accept if, for example, the timestamp is in the future, prior entry hash is incorrect, other partrs are invalid.&lt;/p&gt;

&lt;p&gt;And they use this approach back-and-forth to record all business records.&lt;/p&gt;

&lt;h2 id=&quot;privacy&quot;&gt;Privacy&lt;/h2&gt;

&lt;p&gt;You connect to other entities only by explicit configuration on both sides. All data is end-to-end encrypted through both sides.&lt;/p&gt;

&lt;h2 id=&quot;plausible-deniability-ratchet&quot;&gt;Plausible deniability ratchet&lt;/h2&gt;

&lt;p&gt;You may rotate your key on each turn with the optional “pentultimate signing key and new signing key”. In this case, you and the counterparty will each know your connection is still secure and still know that the prior messages have not been tampered with. But it adds something new.&lt;/p&gt;

&lt;p&gt;If anybody (you, the counterparty, or a third party that somehow got access) tried to publish the event stream, they would also necessarily be publishing the signing keys for each event (up to the most recent one). Therefore, no third party can authenticate that these messages are authentic.&lt;/p&gt;

&lt;p&gt;It would be like if you walked into the bar with an ID card, and your ID card was stapled to a fake-ID-card printing machine!&lt;/p&gt;

&lt;h2 id=&quot;external-time-synchronization&quot;&gt;External time synchronization&lt;/h2&gt;

&lt;p&gt;You may synchronize your entries with external timestamping services (“public notary”) if you care about proving &lt;em&gt;when&lt;/em&gt; certain messages happened.&lt;/p&gt;

&lt;p&gt;Include the most recent Bitcoin network blockhash as part of any event payload. This proves your event was created at some time after that Bitcoin block.&lt;/p&gt;

&lt;p&gt;Include a copy of any event and publish as part of a Bitcoin event. This proves your events was created some time before that Bitcoin block settled.&lt;/p&gt;

&lt;h2 id=&quot;smart-contracts&quot;&gt;Smart contracts&lt;/h2&gt;

&lt;p&gt;The entry payloads may also include other protocols such as Ethereum Virtual Machine code.&lt;/p&gt;

&lt;p&gt;If the notary is configured to reject messages that do not follow the specified protocol then this can maintain a mutual smart contract ecosystem.&lt;/p&gt;

&lt;h2 id=&quot;a-network-of-peers&quot;&gt;A network of peers&lt;/h2&gt;

&lt;p&gt;This approach also scales to a network of peers.&lt;/p&gt;

&lt;p&gt;Remember that when Business B and Business C communicate in this example, they cannot messages they have seen (through Business A) regarding the public notary. If ratcheting is used, the messages they see through Business A may be a forgery of the public notary’s mesages!&lt;/p&gt;

&lt;p&gt;The notary pairs system only guarantees security between relationship pairs. It does not establish stable public identities which can be gossiped between entities.&lt;/p&gt;

&lt;h2 id=&quot;the-limits-of-channels&quot;&gt;The limits of channels&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Public identities are not supported.&lt;/strong&gt; In this topology of pairs:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart TD
    subgraph Private network
    A[Business A] &amp;lt;--&amp;gt; B[Business B]
    B &amp;lt;--&amp;gt; C[Business C]
    A &amp;lt;--&amp;gt; C
    end
    subgraph Public internet
    A &amp;lt;--&amp;gt; I[Pinning to a public notary]
    end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The notary pairs system only guarantees security between relationship pairs. It does not establish stable public identities which can be gossiped between entities. For example, Business B and Business C cannot validate any message regarding the public notary which they have seen through Business A. Recally that if patcheting is used, Business A is fully able to delay and forge messages from the public notary and feed them to its peers. They will be none the wiser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credit systems are not supported.&lt;/strong&gt; It is well established that any credit instruments only works if there is a publicly visible collateral. And debts against it are only truly enforceable if they are publicly recorded against the visible collateral. This is how layer-two networks (“channels”) such as the Lightning Network are able to efficiently move Bitcoin. They:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Publicly secure an asset (e.g. some Bitcoin)&lt;/li&gt;
  &lt;li&gt;Do things&lt;/li&gt;
  &lt;li&gt;Release the asset&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This system only works because everybody can agree that no two overlapping debt instruments are outstanding against a given Bitcoin.&lt;/p&gt;

&lt;p&gt;Furthermore, if you are using the ratchet privacy option, you can’t be sure that any gossip you see outside of your own channel is genuite!&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This system allows any business relationships to benefit from mutual message/document timestamping. This effectively prevents any dispute of document receipt and he-said/she-said timing. It scales to arbitrary kinds of documents and online network access.&lt;/p&gt;
</description>
        <pubDate>Tue, 09 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/notary-pairs</link>
        <guid isPermaLink="true">https://blog.phor.net/notary-pairs</guid>
        
        <category>blockchain</category>
        
        
      </item>
    
      <item>
        <title>Legal resident DAO</title>
        <description>&lt;p&gt;&lt;em&gt;This paper provides a technical explanation of how to send blockchain tokens only to verifiable US citizens. It runs entirely on-chain and is trustless. This approach scales to other jurisdictions and other verifications, and it does not require cooperation from government.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the age of the airdrop, projects wanted to create a token and then give out a limited supply to: special people on GitHub, special people on X, other named individuals.&lt;/p&gt;

&lt;p&gt;But each one of these was implemented the same way: some person creates a bunch of tokens for themself, they set up a webserver, and you that webserver may decide to give some of the tokens to you. You login using GitHub or X or whatever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You&lt;/strong&gt; were proving to the &lt;strong&gt;project owner&lt;/strong&gt; who you are and the &lt;strong&gt;project owner&lt;/strong&gt; gave you tokens.&lt;/p&gt;

&lt;p&gt;System-wise and security-wise this is not interesting. It is a trusted system. They could give the tokens to themselves or anybody.&lt;/p&gt;

&lt;p&gt;But a few cryptographic primatives in wide use today allow us to do trustless verifications for some interesting attestations.&lt;/p&gt;

&lt;p&gt;You can create verifiable proofs of asset ownership and identity without showing that identity to anybody. Let’s see!&lt;/p&gt;

&lt;h2 id=&quot;email-dkim-primative&quot;&gt;Email DKIM primative&lt;/h2&gt;

&lt;p&gt;Email already has domain anti-spoofing checks. Here’s how that works.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart LR
    X[DNS] --&amp;gt;|DKIM key| B
    A[Sender] --&amp;gt;|Email| B[Recipient]
&lt;/code&gt;&lt;/pre&gt;

&lt;ol&gt;
  &lt;li&gt;A sending domain DNS entry recognizes a specific server as authoritative (e.g. Google Workspace)&lt;/li&gt;
  &lt;li&gt;The email sending system publishes DKIM records, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20161025._domainkey.gmail.com&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Sent emails are signed using this key.&lt;/li&gt;
  &lt;li&gt;The recipient verifies against this key and concludes the email is authentic from the sending domain.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;If the email is published, anybody can trustlessly verify it is authentic from the sending domain.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;If you publish the email first, you can reasonably demonstrate that you initiated that action.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When we say to “publish” the email, this means the full email including headers.&lt;/p&gt;

&lt;h2 id=&quot;filesharing-primative&quot;&gt;Filesharing primative&lt;/h2&gt;

&lt;p&gt;InterPlanetary File System (IPFS) and the Solana blockchain both use the same Ed25519 key pair and can cross validate identities.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A person publishes to IPNS with any standard Ed25519 key.&lt;/li&gt;
  &lt;li&gt;Anyone can resolve the IPNS to get the full public key (use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ipfs name resolve&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Convert that public key to Solana’s Base58 address format (one-line of code).&lt;/li&gt;
  &lt;li&gt;Identify if that address is active on Solana and send them tokens.&lt;/li&gt;
  &lt;li&gt;The person who controls the IPNS private key can use any SOL or tokens immediately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This works today, you can tokens directly to anybody who publishes on IPFS/IPNS.&lt;/p&gt;

&lt;p&gt;Working the other direction, you can also check the online/offline status and IP address of such people that are using Solana.&lt;/p&gt;

&lt;h2 id=&quot;github-ssh-key-primative&quot;&gt;GitHub SSH key primative&lt;/h2&gt;

&lt;p&gt;You can use the GitHub API to lookup the public keys for me or anybody using GitHub.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://api.github.com/users/fulldecent/keys&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can use this approach to allow arbitrary GitHub accounts to login to a system you created. Ubuntu has a nice setup process when you create an account: provide your GitHub username and it sets up public-keys to login to your account.&lt;/p&gt;

&lt;p&gt;With a blockchain smart contract, you can preauthorize a list of these keys from targeted GitHub accounts. Then those people can sign a message that is verified on chain. No webserver required, no middleman.&lt;/p&gt;

&lt;h2 id=&quot;use-case-proof-of-billionnaire-status&quot;&gt;Use case: proof of billionnaire status&lt;/h2&gt;

&lt;p&gt;From the email primative, we can parlay this with the fact that investment brokerages will send emails including account details to beneficial owners.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart LR
    X[DNS] --&amp;gt;|DKIM key| B
    A[Sender] --&amp;gt;|Email demonstrating asset ownership| B[Recipient]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you publish this email, this can trustlessly verify that you own a specific asset. Anybody can take your email, verify its authenticity against the brokerage DKIM key. And if they agree that the brokerage sends emails only with factual information, then they can verify the documents without needing to ask the brokerage directly. (They can also see your email address, but we can fix that.)&lt;/p&gt;

&lt;p&gt;If you redact the email (or, lol, just post a screenshot) then the public can no longer validate it against the original DKIM cryptographic signature, anybody could have produced that screenshot. But zero-knowledge proof systems exist where you can &lt;em&gt;describe&lt;/em&gt; the important parts of the email and it will give a non-repudiatable evidence rather than publishing the full email. For example, you could prove:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The DKIM key&lt;/li&gt;
  &lt;li&gt;The email sender&lt;/li&gt;
  &lt;li&gt;A blinded one-way token of your recipient email address or account number&lt;/li&gt;
  &lt;li&gt;Specific text in the email, such as “Account: balance…” for a specific template&lt;/li&gt;
  &lt;li&gt;Zero-knowledge proof demonstrating the full email matches and authenticates as claimed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;dao-for-billionaires&quot;&gt;DAO for billionaires&lt;/h3&gt;

&lt;p&gt;This means you can create a fully-decentralized self-attested club for billionaires. A decentralized program (DAO) will come preloaded with specific acceptable banks/email templates.&lt;/p&gt;

&lt;p&gt;Anybody would just need to produce a valid email attestation showing an account balance and their account number/email address was not previously used. And the DAO admits you as a member.&lt;/p&gt;

&lt;h2 id=&quot;dao-for-citizens-or-voters&quot;&gt;DAO for citizens or voters&lt;/h2&gt;

&lt;p&gt;I live in Montgomery County, Pennsylvania. If you register as a voter with online mailer service, you will receive an email after your ballot is received.&lt;/p&gt;

&lt;p&gt;Using the same approach, it is possible to create a DAO, where anybody (at least MontCo voters) can join after providing anonymous proof that they voted on national election day.&lt;/p&gt;

&lt;p&gt;This same approach can be used for other government identity and action receipts which you receive over email.&lt;/p&gt;

&lt;p&gt;The entire system is trustless, and can be done anonymously on blockchain with a DAO.&lt;/p&gt;

&lt;p&gt;The end result is a blockchain smart contract that trustlessly gives tokens only to US citizens.&lt;/p&gt;

&lt;p&gt;You could of course do other countries.&lt;/p&gt;

&lt;h2 id=&quot;prove-off-chain-activity&quot;&gt;Prove off-chain activity&lt;/h2&gt;

&lt;p&gt;This same email trick allows you to demonstrate ownership of X accounts, ownership of various other online identities, and actions of various kinds across various real words activities.&lt;/p&gt;

&lt;p&gt;I haven’t built any of these systems. Because the world isn’t ready for this future yet.&lt;/p&gt;
</description>
        <pubDate>Tue, 02 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/legal-resident-dao</link>
        <guid isPermaLink="true">https://blog.phor.net/legal-resident-dao</guid>
        
        <category>blockchain,</category>
        
        <category>government</category>
        
        
      </item>
    
      <item>
        <title>How I audit smart contracts in 2026</title>
        <description>&lt;p&gt;&lt;em&gt;How I audit smart contracts: my complete checklist plus a real case study&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I audit smart contracts so you can ship code you trust. This is a repeatable process that catches bugs that matter.&lt;/p&gt;

&lt;p&gt;I have used this workflow on real projects since 2019. It produces publishable, billable results. Sharing it here.&lt;/p&gt;

&lt;p&gt;This applies to audits, and specifically as part of incident response. That means while you are working, life changing amount of money may be getting stolen and that process continues while you work.&lt;/p&gt;

&lt;h2 id=&quot;the-workflow-i-actually-use&quot;&gt;The workflow I actually use&lt;/h2&gt;

&lt;p&gt;I follow these steps every time. They keep the audit honest, public, and useful.&lt;/p&gt;

&lt;p&gt;STEP ZERO IS GET A LOT OF WATER. This could be a very long night. And put food into your favorite food delivery shopping cart. This is a battle and if you run out of water or calories your work could become ineffective.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Engage. Collect:
    &lt;ol&gt;
      &lt;li&gt;The exact code to audit&lt;/li&gt;
      &lt;li&gt;The relevant documentation customers will see&lt;/li&gt;
      &lt;li&gt;Test cases&lt;/li&gt;
      &lt;li&gt;Other institutional knowledge that is requied to use or test the product&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Announce audit to public, if in-scope.&lt;/li&gt;
  &lt;li&gt;Perform audit, see findings list list below.&lt;/li&gt;
  &lt;li&gt;Collate into a report, issues, test cases, or other deliverables as required by client.&lt;/li&gt;
  &lt;li&gt;Publish, if in-scope.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it. Stay focused.&lt;/p&gt;

&lt;h2 id=&quot;the-checklist&quot;&gt;The checklist&lt;/h2&gt;

&lt;h3 id=&quot;verify-collection-and-resources&quot;&gt;Verify collection and resources&lt;/h3&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;
    &lt;p&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Use internet search to confirm all well-known source code/documentation/test cases related to the client and this engagement are actually included in the client-provided scope.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;
    &lt;p&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Use internet search to identify any claimed leakers/evidence of insider threats at the client that may be relevant to the audit scope.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;
    &lt;p&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Get and verify personal contact information for all stakeholders and subject matter experts. Confirm that they are available 24/7 and how to bypass silent settings on their phones. (Audit is sometimes a truly ASAP operation, meaning all participants are expected to forgoe sleep.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;
    &lt;p&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Document your inputs. E.g.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Code was provided privately with SHA-256 hash &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;afcdaf5ddb03b8a227b66a2a0aef41891754ab81450acec7ced296a437db522a&lt;/code&gt;.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;suit-up&quot;&gt;Suit up&lt;/h3&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Install a virtual machine or unpriviledged remote host to perform your work.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;reputation-review&quot;&gt;Reputation review&lt;/h3&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Confirm who wrote the code and how they were paid (check, crypto, etc.).&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Verify the project website has proper WHOIS and contact details.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Review the mission statement of the client organization.
These may be used in a finding if, for example, the organization claims a certain mission and level of control over the product, but the implementation is inconsistent with that.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;supply-chain-audit&quot;&gt;Supply chain audit&lt;/h3&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Ensure the deployed product (if any) matches the provided source code.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Identify all dependencies of the code and project.
    &lt;ul class=&quot;task-list&quot;&gt;
      &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;If code is copy/pasted into the project (e.g. OpenZeppelin Contracts) then identify the specific commit this was pasted from.&lt;/li&gt;
      &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;This includes tooling versions.&lt;/li&gt;
      &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Old versions by themselves may be an audit finding.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Identify all known issues and caveats of these supply chain versions.
For example, Solidity versions before 0.8 did not have integer overflow protection. Before 0.5 had all kinds of craziness.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;identify-any-upgrades&quot;&gt;Identify any upgrades&lt;/h3&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Mutations in smart contract behavior by proxies (“upgrades”) and other mechanisms require the above work to be repeated for each version of the deployed contracts. This also requires a full accounting of how the upgrades happened.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;identify-party-risk&quot;&gt;Identify party risk&lt;/h3&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Find all accounts shown with special permissions against the smart contracts.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Identify the beneficial owners of these accounts (if they are DAOs, smart contracts, “multisigs”, etc.).&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Identify account code (EIP-7702) for external accounts.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Review if the independence of these accounts violates any marketing claims in the documentation or mission statement of the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;intended-code-usage&quot;&gt;Intended code usage&lt;/h3&gt;

&lt;p&gt;Try use cases using a fork of the target blockchain or your own testing instrumentation.&lt;/p&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Consider every documentation which explains how you are supposed to use this product. Write these down.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Consider every NatSpec comment.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Read the code paths and see if at any point there is a violation of any documented (or implied) specifications. These are findings.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Consider anywhere you think you would have implemented this “better” or “differently”. Make a note of that. Compare if their implementation has different edge cases than yours, write these down.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;unexpected-code-usage&quot;&gt;Unexpected code usage&lt;/h3&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;For each code path you considered above, mark any external calls in red. Cross reference that call versus all possible execution contexts. (M×N)&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Read every contract entry point. And consider them versus normal operating storage state situations.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Consider anywhere you think you would have implemented this “better” or “differently”. Make a note of that. Compare if their implementation has different edge cases than yours, write these down.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;undocumented-code&quot;&gt;Undocumented code&lt;/h3&gt;

&lt;p&gt;This is only necessary for interactions including contracts where you do not see the source code. You will need to study the assemply. For example OpenSea Shared Storefront contract.&lt;/p&gt;

&lt;p&gt;For a case study on that reverse engineering and zerodays found &lt;a href=&quot;https://blog.phor.net/opensea-shared-storefront-backdoor#how-do-decompile-and-study-smart-contracts&quot;&gt;see here&lt;/a&gt;.&lt;/p&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Disassemble the code.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Separate each code unit.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Mark in color every potential write operation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL*&lt;/code&gt; .&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Work backwards to color every code unit that could possibly jump to a colored code unit. Repeat to exhaustion.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Delete everything else.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Look for telltale signs of Solidity versions.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Pay attention to storage locations. And figure it out.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;automated-testing&quot;&gt;Automated testing&lt;/h3&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Run existing testing.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Add your edge cases as noted above.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Do fuzzing by hand. Test out-of-range inputs.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Use solhint, slither. Any warning is a finding.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Look for duplication, unused variables, wasteful storage layout.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;change-mindsets-last-pass&quot;&gt;Change mindsets, last pass&lt;/h2&gt;

&lt;p&gt;Whatever mindset, level of sleep or chemicals were in your system… do the opposite of that. Those can all lock you into one way of thinking. To think like an adversary you need many ways of thinking.&lt;/p&gt;

&lt;p&gt;You may do this by napping, jumping jacks, chemicals.&lt;/p&gt;

&lt;h2 id=&quot;sensitivity-and-the-final-report&quot;&gt;Sensitivity and the final report&lt;/h2&gt;

&lt;ul class=&quot;task-list&quot;&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Small findings can combine into big findings. (Old Solidity version + this control structure is not how I would implement it = a broken for loop and complete contract take over.)&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Structure your findings for your written report.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Use basic copyediting techniques.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Mark critical issues with 💣 and material issues with ⚠️.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Include recommendations that are immediately actionable.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Add a “best practices” section that cites the sources I actually respect.&lt;/li&gt;
  &lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; class=&quot;task-list-item-checkbox&quot; disabled=&quot;disabled&quot; /&gt;Ship the report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you’re done. Tell your client exactly how to get a hold of you. Tell your partner what is wake-me-up-worthy. Go sleep for 12 hours.&lt;/p&gt;

&lt;p&gt;For follow up rounds, you may document which findings the client found as acceptable risks.&lt;/p&gt;

&lt;h2 id=&quot;ready-to-get-your-contract-audited&quot;&gt;Ready to get your contract audited?&lt;/h2&gt;

&lt;p&gt;If you want this exact process applied to your project, here is what happens next:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You send me the code and the specification.&lt;/li&gt;
  &lt;li&gt;I run the checklist above.&lt;/li&gt;
  &lt;li&gt;You receive a report in the same format as the Kred example.&lt;/li&gt;
  &lt;li&gt;We iterate in public or private, whichever you prefer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Book a call or just reply to this post with your repo. I answer every serious inquiry.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;https://phor.net/portfolio#smart-contract-audits-zero-day-research-security&quot;&gt;my past audits and zero-day research&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/how-audit-smart-contracts</link>
        <guid isPermaLink="true">https://blog.phor.net/how-audit-smart-contracts</guid>
        
        <category>blockchain</category>
        
        
      </item>
    
      <item>
        <title>Offnet: I built a darkweb inside Ethereum in 2018 (and the contract still works)</title>
        <description>&lt;p&gt;You want to publish a web page.&lt;/p&gt;

&lt;p&gt;No server. No domain. No hosting bill. No one can take it down.&lt;/p&gt;

&lt;p&gt;I solved that in 2018 with &lt;strong&gt;Offnet&lt;/strong&gt;. You store the entire HTML, CSS, and JS directly on Ethereum. Anyone with a browser and a Web3 connection can load it using a special URI. The browser does the rest.&lt;/p&gt;

&lt;p&gt;Here is the exact contract I deployed:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Offnet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contentIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;contentIdentifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contentIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Address: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x8370f43041c98ad30b99c192e8263bcd64529c38&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;You publish by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addFile&lt;/code&gt; with your full file. You pay only the transaction fee.&lt;/li&gt;
  &lt;li&gt;The contract returns the keccak256 hash of your content. That hash is part of your permanent URI.&lt;/li&gt;
  &lt;li&gt;You share the URI with anyone: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?offnet-35fbb6dc3891aacaf1ffa07abec2344fdbc454aab533a2a03bcf93577eb7837b&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;They open that URL with Offnet, the browser intercepts the URI, calls the contract on-chain, and injects the raw content.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the exact service worker that does the magic:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;?offnet-&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;newUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;respondWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;cors&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The full index.html (the entry point users visit) is still live and works today. It gives you the “Load” and “Publish” forms, a list of cool pages, and the security warning.&lt;/p&gt;

&lt;h2 id=&quot;what-you-get&quot;&gt;What you get&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Zero hosting: Tor, no IPFS, no AWS, no Vercel, no domain registrar.&lt;/li&gt;
  &lt;li&gt;True offline mode: sync a local Ethereum node, disconnect the internet, and keep browsing forever. Save the page as a web archive and you literally have the entire site on your laptop.&lt;/li&gt;
  &lt;li&gt;Censorship resistance: the content lives in the blockchain. No single company can delete it.&lt;/li&gt;
  &lt;li&gt;Privacy: you can access the entire Offnet offline if you have a full node.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;why-nobody-scaled-it&quot;&gt;Why nobody scaled it&lt;/h2&gt;

&lt;p&gt;Gas was expensive in 2018–2022. Storing even a medium-sized HTML file cost real money. Service workers have quirks (Firefox and Safari hide them in private browsing).&lt;/p&gt;

&lt;h2 id=&quot;2026-update--it-is-viable-now&quot;&gt;2026 update — it is viable now&lt;/h2&gt;

&lt;p&gt;Dencun blobs and cheap L2s (Base, Arbitrum, Optimism) changed everything. Storage is no longer insane. You can host entire real sites for pennies now. The service-worker pattern still works perfectly.&lt;/p&gt;

&lt;p&gt;I still have the full original files: the two versions of index.html, the service worker, and the exact contract. The demo still loads today.&lt;/p&gt;

&lt;h2 id=&quot;try-it-yourself&quot;&gt;Try it yourself&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Visit the live index.html (or save it locally).&lt;/li&gt;
  &lt;li&gt;Connect any Web3 wallet.&lt;/li&gt;
  &lt;li&gt;Load one of the published pages using the ?offnet- URI format.&lt;/li&gt;
  &lt;li&gt;Publish your own tiny page and share the hash.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This was never meant to replace the normal web. It was a proof that we could build a parallel, serverless, censorship-resistant web using only the tools we already had.&lt;/p&gt;

&lt;p&gt;I built it because I wanted to see if it was possible. It was.&lt;/p&gt;

&lt;p&gt;What are you going to host first?&lt;/p&gt;

&lt;h2 id=&quot;full-indexhtml&quot;&gt;Full index.html&lt;/h2&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;utf-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Offnet&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offnetUri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;URLSearchParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;offnet&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offnetUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;jsonrpc/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offnetUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onreadystatechange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readyState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// APPROACH 1 -- keeps existing HEAD&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//    document.body.innerHTML = request.responseText;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// APPROACH 2 -- replace whole document&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;text/html&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;responseText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// htmlCode is the variable you called newDocument&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;nav&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;navbar navbar-light bg-light d-flex align-items-center&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;background-image:linear-gradient(to right, orange, pink, purple);background-clip:text; -webkit-background-clip:text;color:transparent&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Offnet&lt;span class=&quot;ni&quot;&gt;&amp;amp;trade;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ml-auto form-inline my-0&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mr-3&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;network&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Network:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;select&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;form-control&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;network&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;option&amp;gt;&lt;/span&gt;Ethereum Mainnet (Infura)&lt;span class=&quot;nt&quot;&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;option&amp;gt;&lt;/span&gt;Local node, port 8456&lt;span class=&quot;nt&quot;&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container mt-5 lead&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;animage&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&lt;/span&gt;Offnet URIs&lt;span class=&quot;nt&quot;&gt;&amp;lt;/em&amp;gt;&lt;/span&gt; are qualified to a specific network (set at top) and look like:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;&lt;/span&gt;?offnet=35fbb6dc3891aacaf1ffa07abec2344fdbc454aab533a2a03bcf93577eb7837b&lt;span class=&quot;nt&quot;&gt;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;row mt-5&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Visit any page&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;form-control mb-2&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;offnet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;placeholder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Offnet URI&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;visit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;btn btn-primary mb-2&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Visit&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;    
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Publish a page &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;badge badge-info&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;only pay TX fee&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;file&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mb-2 form-control-file&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;exampleFormControlFile1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;btn btn-primary mb-2&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Publish&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mt-5&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Some cool pages&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Style.css&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; &lt;span class=&quot;ni&quot;&gt;&amp;amp;mdash;&lt;/span&gt; the stylesheet for this page&lt;span class=&quot;nt&quot;&gt;&amp;lt;br&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;?offnet=35fbb6dc3891aacaf1ffa07abec2344fdbc454aab533a2a03bcf93577eb7837b on Ethereum Mainnet&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;&lt;/span&gt;dogs&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; &lt;span class=&quot;ni&quot;&gt;&amp;amp;mdash;&lt;/span&gt; the stylesheet for this page&lt;span class=&quot;nt&quot;&gt;&amp;lt;br&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;?offnet=123456&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;?offnet=123456 on Ethereum Mainnet&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Share other cool pages &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mailto:&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;with us&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Street smarts 💡&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;If you&apos;re reading this page, you might be a crypto billionaire. Before you visit anywhere with Offnet, use a private browsing mode and be extra skeptical of anything you click, lest you be tricked by someone that wants your billions.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text-danger&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;strong&amp;gt;&lt;/span&gt;WARNING:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; If you are reading this page at XXX.NET or your own downloaded copy, then that&apos;s cool. Anything else claiming to be Offnet is unofficial and is a scam.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;


      &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mt-5&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;How does this work?&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Offnet works by intercepting Offnet URIs on web pages you visit, silently fetching and injecting the referenced content.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        Offnet does not store any documents or link to any documents. An Offnet URI is an &lt;span class=&quot;nt&quot;&gt;&amp;lt;em&amp;gt;&lt;/span&gt;identifer&lt;span class=&quot;nt&quot;&gt;&amp;lt;/em&amp;gt;&lt;/span&gt; which uses the contents of a file to succinctly describe that file. In order to retrieve a web page or other file using Offnet you must be connected to a blockchain, such as Ethereum Mainnet. Offnet will retrieve and display requested files from the connected network.
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mt-5&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Maximum security&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        STEP 1: LOCAL NODE &lt;span class=&quot;ni&quot;&gt;&amp;amp;mdash;&lt;/span&gt; Run your own local synchronized blockchain node and choose NETWORK at the top of this page to connect to it.
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        STEP 2: OFFLINE &lt;span class=&quot;ni&quot;&gt;&amp;amp;mdash;&lt;/span&gt; Disconnect from the Internet and all communications services on your device. You can still access all content on Offnet. Yes really.
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        DONE &lt;span class=&quot;ni&quot;&gt;&amp;amp;mdash;&lt;/span&gt; If you destroy your computer now, there will literally be no record on Earth of what you have done with Offnet. No &quot;anonymized&quot; records. No &quot;we promise we don&apos;t keep logs.&quot; Welcome to privacy.
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;footer&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bg-dark py-5 mt-5&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container text-light text-center&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;row&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Offnet&lt;span class=&quot;ni&quot;&gt;&amp;amp;trade;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
            version 1.0-a1
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            Created by &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text-light&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://phor.net&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;William Entriken&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;col&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text-light&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mailto:infura?Requesting to delete content from your local copy of the Ethereum blockchain/standard DMCA form fields&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;DMCA requests&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 17 May 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/offnet</link>
        <guid isPermaLink="true">https://blog.phor.net/offnet</guid>
        
        <category>blockchain</category>
        
        
      </item>
    
      <item>
        <title>The antitrust case against Apple</title>
        <description>&lt;p&gt;Apple, Inc. has built the largest private infrastructure project in human history. They use it to deny competition across multiple valuable markets.&lt;/p&gt;

&lt;h2 id=&quot;the-largest-infrastructure-project-in-human-history&quot;&gt;The largest infrastructure project in human history&lt;/h2&gt;

&lt;p&gt;With over &lt;a href=&quot;https://www.apple.com/newsroom/2026/01/apple-reports-first-quarter-results/&quot;&gt;2.5 billion active devices&lt;/a&gt; from an estimated USD 2.5 trillion in customer investment, Apple’s products are the single largest infrastructure project in human history.&lt;/p&gt;

&lt;p&gt;This surpasses every other great infrastructure project in human history controlled by a single organization:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The Chinese Belt and Road Initiative with &lt;a href=&quot;https://greenfdc.org/china-belt-and-road-initiative-bri-investment-report-2025/&quot;&gt;USD 1.4 trillion in investment&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The Chinese high-speed rail network with &lt;a href=&quot;https://www.yicaiglobal.com/news/chinas-railway-investment-is-poised-to-set-new-record-of-over-usd1274-billion-this-year&quot;&gt;USD 1 trillion in investment&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The US Interstate Highway System with &lt;a href=&quot;https://highways.dot.gov/highway-history/interstate-system/target-27-billion-1955-estimate&quot;&gt;USD 700 billion in investment [2026 dollars]&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a very brief size-up to illustrate.&lt;/p&gt;

&lt;p&gt;Apple &lt;a href=&quot;https://www.apple.com/newsroom/2026/01/apple-reports-first-quarter-results/&quot;&gt;announced in 2026&lt;/a&gt; that it had exceeded an installed base of 2.5 billion active devices. And Apple products have an average selling price about USD 1,000. So that is at least USD 2.5 trillion in investment.&lt;/p&gt;

&lt;p&gt;That is one third of earth’s human population. And the amount of time per day each person uses with these devices is obscene. I’m sure you know it, but I don’t have a reliable number to cite across earth.&lt;/p&gt;

&lt;p&gt;This is infrastructure because it is the basis of commerce and leisure which other people can use directly or build on (with apps). And it is a single project because Apple, Inc. controls the entire thing. (Unlike “the internet” which is actually multiple separate infrastructure projects controlled by many entities.)&lt;/p&gt;

&lt;p&gt;But here’s the real story: Apple uses this unprecedented infrastructure position to systematically deny competition across multiple high-value markets.&lt;/p&gt;

&lt;h2 id=&quot;icloud-the-default-trap&quot;&gt;iCloud: the default trap&lt;/h2&gt;

&lt;p&gt;When you first setup you iPhone, &lt;a href=&quot;https://www.youtube.com/watch?v=AcckZH-PCqQ&quot;&gt;iCloud is enabled by default&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;More importantly, iCloud is stored in a way that by default Apple has &lt;a href=&quot;https://support.apple.com/en-us/102651&quot;&gt;access to every photo you take&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2026-05-11-apple-antitrust-case.webp&quot; alt=&quot;Upgrade to iCloud&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As your iPhone fills up, you can’t use features until you address this issue. iPhone shows you an upgrade path to pay monthly for iCloud. This is the exact moment of maximum user pain — and only Apple gets to appear there. Third-party apps are not allowed know this moment of pain, or to show up in this upgrade path.&lt;/p&gt;

&lt;p&gt;This is an engineered advantage.&lt;/p&gt;

&lt;h2 id=&quot;apple-music-the-unremovable-default&quot;&gt;Apple Music: the unremovable default&lt;/h2&gt;

&lt;p&gt;Apple Music is the default music app on iOS and macOS. You cannot remove it. Press the music button on your keyboard or in CarPlay, and it opens Apple Music — even if you pay for a competing music service and never use Apple Music.&lt;/p&gt;

&lt;p&gt;Oh, and third party music services had to pay 30% of their revenue to Apple, where Apple Music have relatively high cost of goods sold.&lt;/p&gt;

&lt;p&gt;This is an engineered advantage.&lt;/p&gt;

&lt;h2 id=&quot;the-browser-20-billion-for-your-thoughts&quot;&gt;The browser: $20 billion for your thoughts?&lt;/h2&gt;

&lt;p&gt;Apple’s Safari browser is the default browser on iOS and macOS. You cannot remove it. On iOS, competing browsers cannot improve on the rendering speed by making a competing rendering engine.&lt;/p&gt;

&lt;p&gt;Apple doesn’t let them. And Google pays Apple USD 20 billion per year for the search traffic from Safari.&lt;/p&gt;

&lt;p&gt;Building a new rendering engine is a huge undertaking. Probably only Google would do this on iOS. Google would surely rather invest USD 100 billion one time to make a better browser than pay this toll each year. And they could. But…&lt;/p&gt;

&lt;p&gt;Keeping every other browser out is an engineered advantage.&lt;/p&gt;

&lt;h2 id=&quot;the-result&quot;&gt;The result&lt;/h2&gt;

&lt;p&gt;Across multiple markets, Apple has engineered advantages for its own products and systematically denied competition.&lt;/p&gt;

&lt;p&gt;Apple could do this for any industry. If they wanted to make a fast food restaurant, they could ensure that no other fast food restaurant could take orders on their platform. (Fast food restaurants currently do not pay any fees or revenue share to Apple.) Fast food is out of Apple’s current appetite. But as of today, Apple has engineered maximum revenue against the following markets:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;File storage&lt;/li&gt;
  &lt;li&gt;Music&lt;/li&gt;
  &lt;li&gt;Web search&lt;/li&gt;
  &lt;li&gt;Video games&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And there are plenty of other examples.&lt;/p&gt;

&lt;p&gt;Apple has the power to control prices and exclude competitors. Apple’s progress in its secondary products is primarily due to its engineered advantages in its primary products.&lt;/p&gt;
</description>
        <pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/apple-antitrust-case</link>
        <guid isPermaLink="true">https://blog.phor.net/apple-antitrust-case</guid>
        
        <category>apple</category>
        
        <category>antitrust</category>
        
        
      </item>
    
      <item>
        <title>Why don&apos;t people rob the coat check?</title>
        <description>&lt;p&gt;&lt;em&gt;A real-world lesson in custody, incentives and “trustless” systems&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You hand over your $1,200 Canada Goose, your wallet and your keys to a bored college kid behind a folding table. In return you get a little paper stub with a number on it. Then you walk away.&lt;/p&gt;

&lt;p&gt;And yet… almost nobody robs the coat check.&lt;/p&gt;

&lt;p&gt;It’s not because the system is technically brilliant. It’s a paper ticket. It’s not because the attendant is armed or the coats are in a vault. They’re literally hanging on a rack six feet away. Physically, robbing it is laughably easy—especially for the attendant, who has unlimited unsupervised access every single night.&lt;/p&gt;

&lt;p&gt;So why doesn’t robbery happen constantly?&lt;/p&gt;

&lt;h2 id=&quot;surface-level-answers-all-true-none-sufficient&quot;&gt;Surface-level answers (all true, none sufficient)&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The ticket is a crude non-fungible token: one unique claim per item, redeemable only by the rightful holder.&lt;/li&gt;
  &lt;li&gt;Bulky coats are hard to pawn.&lt;/li&gt;
  &lt;li&gt;There are bouncers, cameras, and witnesses.&lt;/li&gt;
  &lt;li&gt;The attendant is dressed differently than guests and may draw suspicion if they try to walk out with a coat.&lt;/li&gt;
  &lt;li&gt;Most humans aren’t criminals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All correct. All incomplete.&lt;/p&gt;

&lt;h2 id=&quot;bear-with-me-for-a-blockchain-comparison&quot;&gt;Bear with me for a blockchain comparison&lt;/h2&gt;

&lt;p&gt;Now imagine the same setup but on a &lt;em&gt;new&lt;/em&gt; blockchain project.&lt;/p&gt;

&lt;p&gt;You deposit your assets into a multisig wallet. The “attendant” is able to honor redemption of your assets, or not. There is no face-to-face interaction, no venue, no reputation, no ongoing business. Just code and anonymity.&lt;/p&gt;

&lt;p&gt;In that world, the “robbery” happens constantly. Rug pulls, drained treasuries, “lost” keys or whatever you want to call it. It’s trivial and consequence-free for the thief because there is no &lt;em&gt;establishment&lt;/em&gt; to protect.&lt;/p&gt;

&lt;p&gt;The technical difference is night and day:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Coat check&lt;/th&gt;
      &lt;th&gt;Anonymous multisig&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Centralized custody, physical enforcement&lt;/td&gt;
      &lt;td&gt;Decentralized custody, zero real-world accountability&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;But the &lt;em&gt;actual&lt;/em&gt; reason people don’t rob the coat check has nothing to do with technology or custody models.&lt;/p&gt;

&lt;h2 id=&quot;the-real-reason-the-establishment-has-too-much-to-lose&quot;&gt;The real reason: the establishment has too much to lose&lt;/h2&gt;

&lt;p&gt;The coat check doesn’t exist in a vacuum. It lives &lt;em&gt;inside&lt;/em&gt; a profitable business—a nightclub, a restaurant, a theater, a wedding venue—that makes money night after night, year after year.&lt;/p&gt;

&lt;p&gt;That establishment has:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Reputation capital&lt;/strong&gt; it cannot afford to burn.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Repeat customers&lt;/strong&gt; who will simply stop coming if coats start disappearing.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Staff&lt;/strong&gt; who know they’ll be fired (and possibly prosecuted) if theft is even &lt;em&gt;suspected&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Social media&lt;/strong&gt; that amplifies any scandal instantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even an &lt;em&gt;unsubstantiated&lt;/em&gt; claim of theft can tank the venue’s Yelp score, get it dragged on TikTok and scare away high-spending customers. The business owner may rather eat the cost of a stolen coat, or fire an attendant, than let a rumor spread. This economic reality is what actually secures the coats—not the paper ticket, not the attendant’s honesty, not blockchain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The system works because an establishment is valuable and theft is an unacceptable risk to that value.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-about-pop-up-events-temporary-establishments&quot;&gt;What about pop-up events, temporary establishments?&lt;/h2&gt;

&lt;p&gt;Can we challenge the assumptions about the establishment above. What about?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A one-night pop-up event with no brand or repeat customers.&lt;/li&gt;
  &lt;li&gt;The last night of a venue that’s closing forever, where the lifelong owner is not present.&lt;/li&gt;
  &lt;li&gt;A venue which already has a reputation for theft.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, what you are showing are establishments that aren’t established. ⊥&lt;/p&gt;

&lt;h2 id=&quot;so-what-does-this-mean-for-crypto-nfts-and-trustless-systems&quot;&gt;So what does this mean for crypto, NFTs, and “trustless” systems?&lt;/h2&gt;

&lt;p&gt;We spent years celebrating anonymous, permissionless, trustless protocols as the future. And in many ways they are.&lt;/p&gt;

&lt;p&gt;But the coat-check analogy reveals the simple truth: &lt;strong&gt;custody and other trust-based applications depend on establishment.&lt;/strong&gt; And this includes reputation, profit motive and other incentives.&lt;/p&gt;

&lt;p&gt;A blockchain multisig run by anonymous signers with no ongoing business can steal from customers tomorrow and the thieves disappear into the ether. You can prevent this by having any multisig or no-recourse custodian be managed by a third-party with reputation to lose. Then after you have a profit-making establishment, think about bringing it back in-house.&lt;/p&gt;

&lt;p&gt;The paper ticket works not because it’s a sacred bond, but because it sits inside an establishment whose profits and reputation are on the line every single night.&lt;/p&gt;

&lt;p&gt;That’s the real security model.&lt;/p&gt;

&lt;p&gt;And it’s why your coat is probably still hanging there when you stumble back at 2 a.m. with (or without!) your little stub in hand. 🎟️&lt;/p&gt;
</description>
        <pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/why-not-rob-coat-check</link>
        <guid isPermaLink="true">https://blog.phor.net/why-not-rob-coat-check</guid>
        
        <category>game</category>
        
        <category>theory</category>
        
        
      </item>
    
      <item>
        <title>My best voice</title>
        <description>&lt;p&gt;I have not always followed this guide. That’s fine. Progress starts from documenting what works.&lt;/p&gt;

&lt;p&gt;This guide collects the voice and style I use when the writing feels most inspired—when it launches standards, templates, and ideas that other people actually adopt and resonate with.&lt;/p&gt;

&lt;p&gt;We are contemplative and intentional about voice because we respect the reader. When writing for a community or project, that respect extends further: it honors their interests and proposes a thoughtful place for them in the world.&lt;/p&gt;

&lt;p&gt;My &lt;em&gt;voice&lt;/em&gt; is therefore direct, practical, and opinionated, always aimed at solving real problems while respecting you—the reader—as a collaborator rather than an audience. It mixes precision where it matters with conversational warmth, draws from the spare clarity and wonder of XKCD.&lt;/p&gt;

&lt;p&gt;My &lt;em&gt;style&lt;/em&gt; is the practical toolkit that supports this: short active sentences, liberal use of lists, tables, diagrams, and clean typography that makes complex ideas immediately usable.&lt;/p&gt;

&lt;p&gt;The sections below lay it out in detail with high-level prose patterns, low-level typography and capitalization rules, human interface best practices, and how to apply this guide in your own work or contributions.&lt;/p&gt;

&lt;h2 id=&quot;high-level-prose-patterns&quot;&gt;High-level prose patterns&lt;/h2&gt;

&lt;p&gt;My voice is direct, practical, and opinionated. I write to solve problems and to inspire others to create better things. Sentences stay short and active. I address &lt;strong&gt;you&lt;/strong&gt;, the reader, directly because this is a conversation, not a lecture.&lt;/p&gt;

&lt;p&gt;I emphasize best practices and production readiness. You will see phrases such as “awesome reusable modules” or “opinionated starting point” because I believe in setting high standards from day one. I use lists, tables, and diagrams liberally. They make complex ideas immediately usable.&lt;/p&gt;

&lt;p&gt;I mix formality where precision matters (see the ERC-721 specification) with conversational warmth where ideas are forming. The common thread is clarity. I avoid fluff. If a sentence does not add value or move the reader forward, I delete it.&lt;/p&gt;

&lt;p&gt;I draw inspiration from XKCD: profound wonder, analysis and humanity. When I put something to words, I want you to feel the same sense of possibility I felt when I first came at the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When creating a standard, template, or invitation to adopt a specification&lt;/strong&gt; I always start with a clear value proposition: why this particular interface deserves to exist and what real-world problem it solves for producers and consumers. Only after that do I deliver an extremely clear and valid list of behaviors.&lt;/p&gt;

&lt;p&gt;This pattern appears throughout my work. In ERC-721 the abstract opens with the concrete benefit (“a standard API for NFTs… to track and transfer”) and immediately paints the diverse universe of use cases so readers can picture their own. The specification then uses RFC-2119 keywords (“MUST”, “SHALL”, “SHOULD”) to define exact behaviors with zero ambiguity. The same flow lives in the swift6-module-template README: value proposition first (“opinionated starting point for awesome, reusable Swift 6 modules”), followed by a bullet list of features and turnkey setup steps.&lt;/p&gt;

&lt;p&gt;The reasoning is simple: when you invite people to plug into a community or ecosystem, you must speak in &lt;em&gt;their&lt;/em&gt; language and give them a clear, respectful connection plan that considers their actual needs. Standards only deserve to be written when multiple people already adhere to them and others depend on the surface area of that interface. (See the full reasoning in “&lt;a href=&quot;https://blog.phor.net/things-that-should-be-standardized&quot;&gt;What kinds of things should be standardized?&lt;/a&gt;”.) The goal is interoperability that reduces waste, not contrived rules that nobody asked for. I therefore maintain the same disciplined documentation style I expect others to follow—precise, readable, and ready for production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deriving authority through references and best practices&lt;/strong&gt; I build credibility by openly recognizing excellent work wherever I find it. I keep a consistent “references” or “best practices” section in almost every project. By naming the inspired souls whose ideas resonate with me, my voice joins a larger chorus and we become louder. You will see this in the swift6-module-template (which cites Swift project recommendations and links to its own Recipe.md), the github-pages-template, and many other repositories. The section is never an afterthought; it is how I show respect for the people who came before and invite others to stand on the same shoulders.&lt;/p&gt;

&lt;p&gt;Examples of this full voice appear in:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The ERC-721 abstract and motivation sections, which explain non-fungible tokens with real-world analogies and invite you to dream up new use cases.&lt;/li&gt;
  &lt;li&gt;The swift6-module-template and github-pages-template READMEs, which list features immediately then give step-by-step instructions.&lt;/li&gt;
  &lt;li&gt;Blog posts that turn personal reflection or technical research into actionable advice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;style-guide&quot;&gt;Style guide&lt;/h2&gt;

&lt;p&gt;Here are the scales and chords that play in this voice.&lt;/p&gt;

&lt;h3 id=&quot;use-active-voice&quot;&gt;Use active voice&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;❌ This report was unable to be sent.
    &lt;ul&gt;
      &lt;li&gt;❓ Did anybody specify that a report was due by a certain time?&lt;/li&gt;
      &lt;li&gt;❓ Does the sender recognize their prior committment to send the report?&lt;/li&gt;
      &lt;li&gt;❓ Did the sender actually start to send the report?&lt;/li&gt;
      &lt;li&gt;❓ Did the sender not send the report because they forgot or some extenuating circumstance?&lt;/li&gt;
      &lt;li&gt;❓ Did the sender send the report but actually the software or network failed to deliver it?&lt;/li&gt;
      &lt;li&gt;❌ This note does not contribute whatsoever to improving the situation in the future.&lt;/li&gt;
      &lt;li&gt;❌ This note is powerless, just like “it did not rain today” recognizes only God decides the weather.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;✅ I failed to send this report on time.
    &lt;ul&gt;
      &lt;li&gt;✅ The sender recognizes (“on time”) that a report was due by a certain time.&lt;/li&gt;
      &lt;li&gt;✅ The sender confirms (“I failed”) a prior committment which they made.&lt;/li&gt;
      &lt;li&gt;✅ The sender acknowledges (“failed to send”) they are the reason the report was not sent on time.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Microsoft Word 95 warned you (your parents?) tirelessly about passive voice. But as corporate bullshitspeak takes over, passive sentence structure buries accountability and lowers our expectations of people we are talking with.&lt;/p&gt;

&lt;p&gt;In east Asian and especially Filipino culture, people use passive voice in the example above to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Avoid shame (this is prideful and places one’s image over the mission of the team 🙁)&lt;/li&gt;
  &lt;li&gt;Avoid confrontation and create harmony (a harmony based on polite words is less valuable that one based on polite actions 🙁)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this light, &lt;mark&gt;we use active voice to be humble, promote cooperation and respect the long-term relationships with our collaborators&lt;/mark&gt;.&lt;/p&gt;

&lt;h2 id=&quot;low-level-typography-and-capitalization&quot;&gt;Low-level typography and capitalization&lt;/h2&gt;

&lt;p&gt;Follow these rules everywhere unless a specific project (such as an academic paper) requires otherwise:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use uppercase letters only at the start of sentences, for proper nouns, and for initialisms. Everything else stays lowercase. (This produces clean, readable prose.)&lt;/li&gt;
  &lt;li&gt;Do not use the Oxford comma.&lt;/li&gt;
  &lt;li&gt;Preserve typos when formatting chat conversations exactly as shown in the blog repository style guide.&lt;/li&gt;
  &lt;li&gt;Cite US court cases in Bluebook style.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Markdown usage follows these conventions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Headings use sentence case.&lt;/li&gt;
  &lt;li&gt;Bold for emphasis.&lt;/li&gt;
  &lt;li&gt;Italics for gentle stress, sarcasm and introduction of words with added baggage.&lt;/li&gt;
  &lt;li&gt;Bullet lists and numbered lists for any sequence of actions or features.&lt;/li&gt;
  &lt;li&gt;Code blocks and inline code for every technical element.&lt;/li&gt;
  &lt;li&gt;Tables for comparisons or configuration variables.&lt;/li&gt;
  &lt;li&gt;Emojis used sparingly (✅ for status, ℹ️ for notes) to add visual cues without clutter.&lt;/li&gt;
  &lt;li&gt;Margin notes on the right side of blog pages when useful (via the .margin-note class).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For web documents, I maintain consistent notes about how to create slugs and images (here is &lt;a href=&quot;https://github.com/fulldecent/blog.phor.net/blob/fb58b4b81f24962f7bbcdb76d1e19648b1131018/README.md#article-images&quot;&gt;an example for this blog&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;hig-best-practices-in-brief&quot;&gt;HIG best practices (in brief)&lt;/h2&gt;

&lt;p&gt;Human interface guidelines here mean making documentation and interfaces instantly usable. The principles appear throughout my templates and standards work:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Provide turnkey working code or examples immediately.&lt;/li&gt;
  &lt;li&gt;Include testing, linting, and CI from day one.&lt;/li&gt;
  &lt;li&gt;Use semantic versioning, changelogs, and clear folder structures.&lt;/li&gt;
  &lt;li&gt;Make setup reproducible with environment variables or Docker containers.&lt;/li&gt;
  &lt;li&gt;Test hyperlinks, structured data, and accessibility as part of every build.&lt;/li&gt;
  &lt;li&gt;Prefer permanent, stable URLs even when content evolves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These practices come from real-world experience shipping Swift modules, Ethereum standards, and Jekyll sites. They reduce friction for contributors and end users alike.&lt;/p&gt;

&lt;h2 id=&quot;how-to-use-this-guide&quot;&gt;How to use this guide&lt;/h2&gt;

&lt;p&gt;Every person has a voice. Document it somewhere, preferably online.&lt;/p&gt;

&lt;p&gt;Communities and organizations (if we shall anthropomorphize them) have voices too. Document it somewhere, preferably online.&lt;/p&gt;

&lt;p&gt;At a minimum, your copy editor will then have a basis for holding you accountable. And better, they can find if your voice has grown, and distill that insight into… a pull request against that documentation!&lt;/p&gt;
</description>
        <pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/my-best-voice</link>
        <guid isPermaLink="true">https://blog.phor.net/my-best-voice</guid>
        
        <category>ethics</category>
        
        <category>best-practice</category>
        
        
      </item>
    
      <item>
        <title>TRON VM storage collision vulnerability</title>
        <description>&lt;p&gt;Critical TVM storage key truncation to 128 bits leading to arbitrary slot overwrites, birthday attacks, and potential network fork.&lt;/p&gt;

&lt;h2 id=&quot;executive-summary&quot;&gt;Executive summary&lt;/h2&gt;

&lt;p&gt;The execution layer of TRON Virtual Machine (TVM) incorrectly mangles the location of contract storage slots. Specifically, storage keys that differ only in their upper 128 bits will collide and overwrite each other. Also, storage from one smart contract can overwrite storage from another contract if the addresses are similar enough. This is a fundamental error in the official java-tron implementation where it fails to implement the specification advertised on the official TVM documentation, and it breaks advertised compatibility with Ethereum Virtual Machine (EVM).&lt;/p&gt;

&lt;p&gt;The impact is severe: Attacker-controlled contract deployment + birthday collision is now feasible in 2^64 operations instead of the 2^128 operations advertised. This order of birthday collisions are already demonstrated in the wild and are likely to be deployed on TRON someday even unintentionally. Stealing tokens from any contract on TRON is possible with 2^128 hash difficulty instead of the advertised 2^256. If multiple diverse clients are running on the network, it is possible to cause a network fork.&lt;/p&gt;

&lt;h2 id=&quot;technical-background&quot;&gt;Technical background&lt;/h2&gt;

&lt;p&gt;Ethereum Virtual Machine treats every contract’s storage as a map of &lt;strong&gt;2^256 independent 256-bit keys&lt;/strong&gt;. Each slot is completely isolated. And the &lt;a href=&quot;https://developers.tron.network/docs/opcodes&quot;&gt;TRON Virtual Machine specification&lt;/a&gt; also provides this same guarantee:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TVM opcodes are the same as EVM except for TRON-specific opcodes.&lt;/p&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSTORE&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storage[key] := val&lt;/code&gt;&lt;/p&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SLOAD&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val := storage[key]&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, the TRON Virtual Machine implementation (java-tron) &lt;a href=&quot;https://github.com/tronprotocol/java-tron/blob/7e5bbbd21e26f2fb0c60de0e5f88be9dc5e807db/actuator/src/main/java/org/tron/core/vm/program/Storage.java#L46-L54&quot;&gt;does something very different&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addrHash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractVersion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sha3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;arraycopy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addrHash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;arraycopy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is the bit layout:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;---
config:
  packet:
    showBits: false # Cheating because Mermaid too small with 256 bits
---
packet
0-15: &quot;addrHash prefix&quot;
16-31: &quot;lower key bits&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This means that TVM reuses storage slots across all contracts with similar addresses. And it shares storage slots where keys are similar.&lt;/p&gt;

&lt;h2 id=&quot;activation-method-how-to-trigger-it&quot;&gt;Activation method (how to trigger it)&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Deploy any contract on Tron (mainnet or Nile testnet).&lt;/li&gt;
  &lt;li&gt;Write to storage slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Write to storage slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2^128&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Read back slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; — it now contains the value from slot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2^128&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works in &lt;strong&gt;one transaction&lt;/strong&gt; and requires no special permissions.&lt;/p&gt;

&lt;h3 id=&quot;proof-of-concept-poc&quot;&gt;Proof of concept (PoC)&lt;/h3&gt;

&lt;p&gt;Here is a minimal Solidity contract that demonstrates the collision:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[!CAUTION]&lt;/p&gt;

  &lt;p&gt;Do not deploy this contract to mainnet!&lt;/p&gt;

  &lt;p&gt;If multiple diverse clients are running on the network, deploying this contract will cause a network fork.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Storage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is another implementation using inline assembly:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StorageCollisionPoC&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Write to slot 1 (low key)
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sstore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0000000000000000000000000000000000000000000000000000000000000003&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// value = 3
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Write to slot 2^128 + 1 (high key that collides if upper 128 bits are truncated)
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;highKey&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x0000000000000000000000000000000100000000000000000000000000000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sstore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0000000000000000000000000000000000000000000000000000000000000004&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// value = 4
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Helper view function to read any slot (for testing)
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;readSlot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Confirm collision: will return 2 on java-tron, but 1 on a correct implementation
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;readSlot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is another implementation of forking using 9 bytes of contract deployment bytecode.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-evm&quot;&gt;305f55303060801b55
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;On a correct EVM (Ethereum, Polygon, BSC, etc.):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getNumber()&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On TRON Virtual Machine:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getNumber()&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4&lt;/code&gt; — because keys &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2^128&lt;/code&gt; collide when the upper 128 bits are discarded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that in TronIDE you will see the correct value. This is because TronIDE uses a different storage implementation for testing that does not have the same bug. The bug only exists in the actual TVM execution environment on the blockchain.&lt;/p&gt;

&lt;p&gt;You can deploy this on Nile testnet today (do not deploy to mainnet, see note above) and verify with a block explorer (TronScan). See a similar contract &lt;a href=&quot;https://tronscan.org/#/transaction/e9ccd262eab30f5ae07f27ec9545a59dd092ec2ac27df25faefd313caf2e5c8f&quot;&gt;that is already deployed&lt;/a&gt;. And you can query it using the key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; and the key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;340282366920938463463374607431768211457&lt;/code&gt; (2^128 + 1). Compare that to the previous transaction that set that storage value.&lt;/p&gt;

&lt;h3 id=&quot;forking-proof-of-concept&quot;&gt;Forking proof of concept&lt;/h3&gt;

&lt;p&gt;In TRON Virtual Machine, unlike Ethereum, the storage root is not included in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accountStateRoot&lt;/code&gt; of the block header. And therefore the example above will not cause a concensus failure by way of the state root being different for two different nodes.&lt;/p&gt;

&lt;p&gt;However, if you look closer, notice how the first storage change is at one address and the second storage change is at a different address. Well, according to &lt;a href=&quot;https://developers.tron.network/docs/opcodes&quot;&gt;the TRON energy specification&lt;/a&gt;, a proper consensus client would bill this energy usage twice at full rate. But the current java-tron implementation only charges the first storage change at the full rate, and the second storage change at a much lower rate (because it thinks it is overwriting an existing slot instead of writing to a new slot).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;energy_cost = (oldValue == null &amp;amp;&amp;amp; val != 0) ? 20000 : (oldValue != null &amp;amp;&amp;amp; value == 0) ? 5000 : 5000&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means that if java-tron is running today on mainnet and a different client is also running on mainnet that is properly implemented, then the same transaction will be accepted by both clients but will have different energy costs. This results in a fork of the network!&lt;/p&gt;

&lt;p&gt;Be very careful before attempting to deploy the above contract because it might break the entire TRON network!&lt;/p&gt;

&lt;h2 id=&quot;root-cause-exact-source&quot;&gt;Root cause (exact source)&lt;/h2&gt;

&lt;p&gt;The bug lives in the official java-tron reference client:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;actuator/src/main/java/org/tron/core/vm/program/Storage.java&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// = 128 bits&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addrHash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contractVersion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sha3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;arraycopy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addrHash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ← ONLY 128 bits&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;arraycopy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;PREFIX_BYTES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// ← ONLY lower 128 bits!&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Every 256-bit storage key (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataWord&lt;/code&gt;) has its &lt;strong&gt;upper 128 bits discarded&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;Only the lower 128 bits + a 16-byte address prefix become the actual database key (LevelDB/RocksDB).&lt;/li&gt;
  &lt;li&gt;A singleton storage instance is shared across all contracts, and only part of the address is used.&lt;/li&gt;
  &lt;li&gt;Cross-contract collisions are possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;full-impact-analysis&quot;&gt;Full impact analysis&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity:&lt;/strong&gt; Critical&lt;/p&gt;

&lt;h3 id=&quot;1-birthday-attack-on-hashed-slots&quot;&gt;1. Birthday attack on hashed slots&lt;/h3&gt;

&lt;p&gt;Most contracts use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; for mappings and dynamic arrays:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Expected entropy: 2^256 (full key uniqueness).&lt;/li&gt;
  &lt;li&gt;With java-tron: only the lower 128 bits of the key are effectively used after truncation → effective entropy drops to 2^128 per contract.&lt;/li&gt;
  &lt;li&gt;A birthday-paradox collision search now becomes feasible in ≈ 2^64 operations (feasible today with modern GPU clusters or dedicated hardware in weeks to months for a motivated attacker).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An attacker can:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Attacker-controlled deployment: An attacker deploys their own high-value contract (e.g., SunSwap pool, USDT-TRC20 bridge, token) using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; to control/predict the address and initial storage layout. They can then:
    &lt;ul&gt;
      &lt;li&gt;Compute colliding key pairs offline (via birthday attack on the lower 128 bits).&lt;/li&gt;
      &lt;li&gt;Later deploy a second malicious contract to the colliding “prefix space.”&lt;/li&gt;
      &lt;li&gt;Use the collision to overwrite critical state in their “first” contract (e.g., set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balanceOf(attacker) = totalSupply&lt;/code&gt;, change owner, drain funds).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Steal from an arbitrary existing high-value contract: Requires finding a colliding key for a specific existing storage slot (preimage attack) → still 2^128 difficulty (infeasible today). This is much easier than the advertised 2^256 difficulty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If somebody else also knows this vulnerability, they may have already done the first step above and be prepared to deploy the second contract anytime and drain all the funds from an existing high-value contract.&lt;/p&gt;

&lt;h3 id=&quot;2-direct-overwrite-of-fixed-slots&quot;&gt;2. Direct overwrite of fixed slots&lt;/h3&gt;

&lt;p&gt;Any contract using low-numbered slots (common in proxies, upgradeable contracts, or assembly code) can have those slots silently overwritten by anyone who knows the colliding high key.&lt;/p&gt;

&lt;h3 id=&quot;3-underhanded-contract-behavior&quot;&gt;3. Underhanded contract behavior&lt;/h3&gt;

&lt;p&gt;An attacker can deploy a malicious contract that appears to be permissionless, but actually they maintain administrative control, by using storage collisions to overwrite critical state.&lt;/p&gt;

&lt;p&gt;This is simple, and anybody reviewing the contract source code and expecting java-tron to work as advertised would not predict the actual program behavior.&lt;/p&gt;

&lt;h3 id=&quot;4-unintentional-cross-contract-collisions&quot;&gt;4. Unintentional cross-contract collisions&lt;/h3&gt;

&lt;p&gt;Even unintentional collisions pose a real risk when contracts share similar address prefixes (first 128 bits / 16 bytes) or when using low/predictable keys. For example, the OpenSea Seaport project uses deployment addresses with many leading zero bits (&lt;a href=&quot;https://github.com/ProjectOpenSea/seaport?tab=readme-ov-file#deployments-by-evm-chain&quot;&gt;57 bits now&lt;/a&gt;, increasing with new versions). If Seaport (the dominant NFT marketplace protocol) deploys on Tron and reaches ~16 leading zero bytes in an address, all versions/deployments sharing that 128-bit prefix would have fully colliding storage spaces. Any write to one contract’s storage would silently corrupt or overwrite state in the others — breaking approvals, listings, or escrow logic across versions without any intentional exploit.&lt;/p&gt;

&lt;h3 id=&quot;5-chain-fork&quot;&gt;5. Chain fork&lt;/h3&gt;

&lt;p&gt;If there are multiple clients running on the network, then the same transaction will be accepted by all clients but will have different energy costs. This will cause a fork of the network between clients that implement the correct storage model and the java-tron clients that implement the incorrect storage model.&lt;/p&gt;

&lt;h2 id=&quot;cve-style-impact-statement&quot;&gt;CVE-style impact statement&lt;/h2&gt;

&lt;p&gt;Allows an attacker to cause storage collisions across all contracts on the TRON network, enabling theft of tokens, manipulation of contract state, and potential network forks. The vulnerability arises from a fundamental flaw in the java-tron TVM implementation where 256-bit storage keys are truncated to 128 bits, resulting in predictable collisions. This can be exploited with a single transaction and requires no special permissions, making it a critical risk for all users and developers on the TRON platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CVSS 3.1 Score (estimated):&lt;/strong&gt; 9.8 (Critical) - AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H&lt;/p&gt;

&lt;h2 id=&quot;recommended-resolution&quot;&gt;Recommended resolution&lt;/h2&gt;

&lt;p&gt;Tron should immediately:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compose()&lt;/code&gt; to use the full 256 bits of the key and the full address hash to compute the storage key, as per the original specification. A practical solution is to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(addrHash || key)&lt;/code&gt; as the storage key since it will have sensitivity to all bits and it fits in the same width that is used today.&lt;/li&gt;
  &lt;li&gt;Add a new contract version flag and enforce full 256-bit keys going forward while maintaining backward compatibility for existing contracts.&lt;/li&gt;
  &lt;li&gt;Redeploy and migrate any high value contracts to the new version.&lt;/li&gt;
  &lt;li&gt;Update TVM documentation to stop claiming full EVM compatibility until fixed.&lt;/li&gt;
  &lt;li&gt;Review all high-value contracts on Tron for evidence of collision attempts. (i.e. attacker-controlled contract deployment + birthday collision)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A fix in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compose()&lt;/code&gt; plus a hard fork would resolve it.&lt;/p&gt;

&lt;h3 id=&quot;timeline--disclosure&quot;&gt;Timeline &amp;amp; disclosure&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;2022-11-12 Discovery&lt;/li&gt;
  &lt;li&gt;2026-03-18 Private report to TRON DAO via HackerOne&lt;/li&gt;
  &lt;li&gt;2026-03-24 TRON responded on HackerOne: “Thank you for your report and contribution to our security program. Following a thorough evaluation, we found this report is duplicate. This report will now be closed.” They did not ask me to maintain confidentiality and closed the issue.&lt;/li&gt;
  &lt;li&gt;2026-03-24 Public disclosure on blog.phor.net&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 24 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://blog.phor.net/tron-vm-storage-vulnerability</link>
        <guid isPermaLink="true">https://blog.phor.net/tron-vm-storage-vulnerability</guid>
        
        <category>blockchain</category>
        
        <category>security</category>
        
        <category>zeroday</category>
        
        
      </item>
    
  </channel>
</rss>