<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: DC</title>
    <description>The latest articles on DEV Community by DC (@dc600).</description>
    <link>https://dev.to/dc600</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2900291%2F39cae2b5-c4d4-436f-a982-cad67f3b24ae.jpg</url>
      <title>DEV Community: DC</title>
      <link>https://dev.to/dc600</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dc600"/>
    <language>en</language>
    <item>
      <title>Zero-Trust Networking to Control-Plane Privacy: How Diode Scales on Oasis</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Tue, 25 Aug 2026 07:27:03 +0000</pubDate>
      <link>https://dev.to/dc600/zero-trust-networking-to-control-plane-privacy-how-diode-scales-on-oasis-29jj</link>
      <guid>https://dev.to/dc600/zero-trust-networking-to-control-plane-privacy-how-diode-scales-on-oasis-29jj</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpl6swpvez3o6d1w44lmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpl6swpvez3o6d1w44lmd.png" alt=" " width="799" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enterprise integration of on-chain techniques is steadily growing, but is still far below blockchain's scope and potential. The main reason is that most crypto projects are built for users willing to jump through the hoops of complex interfaces and less-than-seamless experiences. &lt;/p&gt;

&lt;p&gt;So, it is refreshing to see a project like Diode that aims to reach users who don't need to know or learn about underlying technologies to avail the benefits of some product or service. Along the way, Diode has fully embraced the privacy-first philosophy. This encompasses team communication, zero-trust networking, and AI, with &lt;a href="https://oasis.net/" rel="noopener noreferrer"&gt;Oasis&lt;/a&gt; doing the heavy lifting behind the scenes by bringing private data, verifiable execution, and programmable policies to the table. &lt;/p&gt;

&lt;p&gt;This is especially beneficial for enterprise users who need to adhere to stringent regulations concerning data liability, and where high compliance levels mean zero tolerance for external access to their information.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Three Acts of Diode&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What &lt;a href="https://diode.io/" rel="noopener noreferrer"&gt;Diode&lt;/a&gt; is doing is best understood by looking at their three-layered approach.&lt;/p&gt;

&lt;p&gt;In the first layer, they have introduced zero-trust networking (ZTN), which deserves a more thorough discussion later. Suffice here to say that Diode's WireGuard-native network is unique in its offering of blockchain-based identities, and is more cost-efficient than the alternatives, Tailscale or Zscaler. This is achieved by operating on bandwidth fees instead of traditional per-device charges.&lt;/p&gt;

&lt;p&gt;In the second layer, Diode has improved upon team communication by creating a blockchain-defined communication perimeter. As a result, it works virtually like a private Slack where each user holds an identity contract. This is a multi-sig wallet linking their devices to a single verifiable identity, resulting in a secure "zone" of communication. Such zones then control who can read messages, share files, and access tunneled browsing or encrypted dashboards.    &lt;/p&gt;

&lt;p&gt;In the third layer, there is private AI, coordinated by a B2B system. It enables organizations to query their own data via an LLM interface. With no sensitive information ever going out to any public platforms, access control is the main focus here. Oasis-anchored access control lists (ACLs) set predefined parameters, governing which tools each team can connect, which LLMs are available for data query, and what filters can determine the output.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;More on ZTNA&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk8s9p9yxh1cue9ed0tkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk8s9p9yxh1cue9ed0tkt.png" alt=" " width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before going any further, let's take a closer look at Diode's privacy-focused zero-trust network access (ZTNA) model, marking their first collaboration with Oasis. ZTN is an alternative to VPN and can replace it altogether as the future method for secure communication. This is an excellent example of a Decentralized Physical Infrastructure Network (DePIN) use case providing SaaS solutions.&lt;/p&gt;

&lt;p&gt;Diode made the on-chain logic used in device onboarding and access permissions in the ZTNA model confidential and secure with Sapphire’s smart privacy infrastructure. This resulted in beefing up the encryption capabilities for decentralized messaging, p2p tunnels, and on-chain proxy services. Users can also avail benefits like connecting to servers, IoT devices, and remote workers to private network assets, all with zero data exposure risk.&lt;/p&gt;

&lt;p&gt;The significance of this privacy-first ZTNA model as the fundamental layer of Diode's system is that both the other layers - team communication and private AI - are built on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Oasis Tech Integration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The role of Oasis in Diode's development has grown in scope and impact as the tech integration is crucial across all these different layers. Typical blockchain transparency means familiarity with contract structure can potentially let anyone identify which wallets are in a given zone or which device keys belong to an identity. Oasis prevents this with control plane privacy, hardcoded with data confidentiality and end-to-end encryption.&lt;/p&gt;

&lt;p&gt;So now, to get even access to read the participating public keys in a Diode zone, a user needs to be a member of that zone contract. And the metadata always stays private by default. Moreover, for secure and seamless networking, WireGuard configurations, SSH keys, and device information are stored in Oasis perimeter contracts. The critical importance of going privacy-first is also demonstrated at the private AI layer, involving the Oasis-anchored ACLs. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Proof of Concept: On-chain Energy RWA With Trust Layer&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fapivbibxh8smi7zsqr42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fapivbibxh8smi7zsqr42.png" alt=" " width="800" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a &lt;a href="https://diode.io/blog/diode-cleanconectai-oasis-verfiable-rwa" rel="noopener noreferrer"&gt;proof of concept&lt;/a&gt;, applying the Oasis-Diode collaborative infrastructure scope to the real-world assets (RWA) space in a dynamic 3-way partnership that includes CleanConnect for oil and gas certification data.&lt;/p&gt;

&lt;p&gt;Here, the AI-driven framework needs verifiable trust, which Oasis facilitates by bringing together Diode Nexus and CleanConnect's ProveZero multi-certification pathways. The partnership showcases the incorporation of adequate safeguards for regulated industrial data while delivering authenticated production proofs and ensuring the validity of on-chain RWA.&lt;/p&gt;

&lt;p&gt;CleanConnect's ProveZero AI-powered camera systems monitor for physical breaches, detect liquid leaks using machine learning, flag hard hat violations, and image methane in the infrared spectrum. As an application of this monitoring system, Chevron qualified for a multi-billion-dollar drilling lease.&lt;/p&gt;

&lt;p&gt;When verifiability at source is added to the mix, it becomes a crucial factor. With the cameras paired with blockchain-tied device identity, the generated data is routed via Sapphire smart contract-enabled ZTNA. &lt;/p&gt;

&lt;p&gt;All this together carries significant regulatory weight, as auditors can review and confirm the footage and sensor outputs in an unbroken provenance trail. It also enables producers, traders, and buyers to access cryptographic proof that the attributes encoded in the certification data, including ISO 14067, ISCC, EO100, MiQ, OGMP, EUMR, etc, are real and verified. This also authenticates a secure, single, auditable chain of custody across major global standards simultaneously.&lt;/p&gt;

&lt;p&gt;This is a scalable model for Oasis trust layer integration, assuring confidentiality, compliance, and control in private, automated, and cross-vendor AI systems. It also addresses the trust gap in current certification systems. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Final Words&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Diode and Oasis coming together provides a working example for next-gen enterprise-grade privacy infrastructure. Diode is already working on making team communication and private AI products available for a wider user base. With &lt;a href="https://oasis.net/" rel="noopener noreferrer"&gt;Oasis&lt;/a&gt;'s tech stack taking care of confidentiality, data is no longer entrusted blindly but is verifiably secure.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>ai</category>
      <category>privacy</category>
    </item>
    <item>
      <title>ROFLize an App: Bonus Guide to Features &amp; Troubleshooting (Part 2)</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Fri, 14 Aug 2026 06:12:11 +0000</pubDate>
      <link>https://dev.to/dc600/roflize-an-app-bonus-guide-to-features-troubleshooting-part-2-2j2c</link>
      <guid>https://dev.to/dc600/roflize-an-app-bonus-guide-to-features-troubleshooting-part-2-2j2c</guid>
      <description>&lt;p&gt;In this 2-part bonus guide on the features and troubleshooting once you ROFLize an app, the &lt;a href="https://dev.to/dc600/roflize-an-app-bonus-guide-to-features-troubleshooting-part-1-324d"&gt;first part&lt;/a&gt; covered in detail the marketplace, secrets, and persistent storage. Let's continue.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Public Variables&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You will remember that we learned about secrets for confidential values. But an app may also consist of containers that need to access non-sensitive values and configurations. API endpoints, contract addresses, feature flags, etc are some examples of information that do not have or need any confidential attributes. This is when we use &lt;strong&gt;public variables&lt;/strong&gt;. They are basically arbitrary key-value pairs that are exposed to containers as environment variables.&lt;/p&gt;

&lt;p&gt;You can manage these public variables using the &lt;a href="https://docs.oasis.io/build/tools/cli/rofl#public-var" rel="noopener noreferrer"&gt;Oasis CLI&lt;/a&gt;. Take this example where we create a public variable called &lt;code&gt;API_URL&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"https://api.example.com"&lt;/span&gt; | oasis rofl public-var &lt;span class="nb"&gt;set &lt;/span&gt;API_URL -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice that this command only updates the local app manifest file. The public variable, however, is not yet propagated to the app. As a result, you will be able to easily configure as many public variables as you want without having to constantly update the on-chain app configuration.&lt;/p&gt;

&lt;p&gt;Once the required public variables are created, you can update all of them in the on-chain configuration using the usual command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Oasis CLI documentation is useful if you need to consult comprehensive public variable management commands, including importing from &lt;code&gt;.env&lt;/code&gt; files, removing public variables, and other advanced features.&lt;/p&gt;

&lt;p&gt;Now, inside the containers, the public variables can be passed via environment variables. This is possible because each public variable is automatically exposed in the Compose environment and can be used in the Compose file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.io/library/alpine:3.21.2@sha256:f3240395711384fc3c07daa46cbc8d73aa5ba25ad1deb97424992760f8cb2b94&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "API URL is $API_URL"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;API_URL=${API_URL}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;rofl.yaml Manifest File&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before proceeding in this section, let's familiarize ourselves with the &lt;strong&gt;metadata&lt;/strong&gt; in the yaml root, consisting of these valid fields. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: A short name for your app that is readable by humans. e.g. &lt;code&gt;my-app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;version&lt;/code&gt;: The ROFL version you are using. e.g. &lt;code&gt;0.1.1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;repository&lt;/code&gt;: A path to the git repository. e.g. &lt;code&gt;https://github.com/user/my-app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;author&lt;/code&gt;: The author name and the e-mail address. e.g., if you are John Doe, then it will show &lt;code&gt;John Doe &amp;lt;john@doe.com&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;license&lt;/code&gt;: The ROFL license in &lt;a href="https://spdx.org/licenses/" rel="noopener noreferrer"&gt;SPDX&lt;/a&gt; format. e.g. &lt;code&gt;Apache-2.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tee&lt;/code&gt;: The Trusted Execution Environment type that is being used. &lt;code&gt;tdx&lt;/code&gt; is the default option, while &lt;code&gt;sgx&lt;/code&gt; is also valid.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kind&lt;/code&gt;: As outlined in the initialization process of the &lt;a href="https://dev.to/dc600/roflize-an-app-part-1-rofl-workflow-to-initialization-4m78"&gt;workflow&lt;/a&gt;. Valid options for TDX TEE are &lt;code&gt;containers&lt;/code&gt;, which is the default, or &lt;code&gt;raw&lt;/code&gt;. If you use SGX TEE, then only &lt;code&gt;raw&lt;/code&gt; is the valid option.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;App Resources (&lt;code&gt;resources&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each containerized app running in ROFL needs pre-defined resources such as the number of assigned vCPUs, amount of memory, storage requirements, GPUs, etc, for its execution. In the app manifest file, these will be headed under &lt;code&gt;resources&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt;
  &lt;span class="na"&gt;cpus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-persistent&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you decide to change the requested resources, it will result in the creation of a different enclave identity for the app. Then you will have to update the policy accordingly. &lt;/p&gt;

&lt;p&gt;Let's now see what these resources signify.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory (&lt;code&gt;memory&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
The amount of memory is specified in megabytes. It is initialized to &lt;code&gt;512&lt;/code&gt; by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;vCPU Count (&lt;code&gt;cpus&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
The number of vCPUs allocated to the VM. It is initialized to &lt;code&gt;1&lt;/code&gt; by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Storage (&lt;code&gt;storage&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
You can choose different storage options for your ROFL app based on its utility. Currently, it can be one of four options.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;disk-persistent&lt;/code&gt;: When the disk of the given size is persistent, it is encrypted and authenticated using a key derived by the decentralized on-chain key management system after successful attestation. This is what our example shows.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;disk-ephemeral&lt;/code&gt;: When the disk of the given size is ephemeral, it is encrypted and authenticated using an ephemeral key randomly generated on each boot. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ram&lt;/code&gt;: Here, an ephemeral filesystem is entirely contained in encrypted memory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;none&lt;/code&gt;: Here, no storage provision has been made. This option is not valid for containerized apps, so you have to choose one of the previous three.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;size&lt;/code&gt; field defines the amount of storage to provision in megabytes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Artifacts (&lt;code&gt;artifacts&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This configures locations of artifacts used during the ROFL build process with &lt;code&gt;builder&lt;/code&gt;, &lt;code&gt;firmware&lt;/code&gt;, &lt;code&gt;kernel&lt;/code&gt;, &lt;code&gt;stage2&lt;/code&gt;, &lt;code&gt;container.runtime&lt;/code&gt;, and &lt;code&gt;container.compose&lt;/code&gt; as supported fields. If any fields are left unspecified, they will use the default artifacts from the CLI. For containerized apps, &lt;code&gt;container.compose&lt;/code&gt; points to the Compose file included in the ROFL bundle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;compose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;compose.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deployments (&lt;code&gt;deployments&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This contains ROFL deployments on specific networks.&lt;/p&gt;

&lt;p&gt;The deployment you have defined will show as &lt;code&gt;deployment_name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Deployment artifacts are optional and merged field by field on top of global &lt;code&gt;artifacts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deployments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;testnet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;testnet&lt;/span&gt;
    &lt;span class="na"&gt;paratime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sapphire&lt;/span&gt;
    &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;compose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;compose.testnet.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are four components to &lt;code&gt;policy&lt;/code&gt; under which your app will spin up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;quotes&lt;/code&gt;: Include TEE-specific policy requirements such as the TCB validity period and the minimum TCB-R number. This helps to indicate what security updates must be applied to the given platform. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enclaves&lt;/code&gt;: Include permissioned enclave IDs for running your app.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;endorsements&lt;/code&gt;: Include a list of conditions defining who can run the app.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;any: {}&lt;/code&gt; indicates any node can run the app. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node: &amp;lt;node_id&amp;gt;&lt;/code&gt; indicates only a specified node ID can run the app.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;provider: &amp;lt;address&amp;gt;&lt;/code&gt; indicates nodes belonging to the specified ROFL provider can run the app.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;provider_instance_admin: &amp;lt;address&amp;gt;&lt;/code&gt; indicates machines having the specified admin can run the app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can choose one or multiple conditions in a nested format by using &lt;code&gt;and&lt;/code&gt; and &lt;code&gt;or&lt;/code&gt; operators.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;policy.yaml&lt;/span&gt;

&lt;span class="na"&gt;endorsements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;and&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oasis1qp2ens0hsp7gh23wajxa4hpetkdek3swyyulyrmz&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;or&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;provider_instance_admin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oasis1qrk58a6j2qn065m6p06jgjyt032f7qucy5wqeqpt&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;provider_instance_admin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oasis1qqcd0qyda6gtwdrfcqawv3s8cr2kupzw9v967au6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example indicates that the app can be run only on the specified provider, and on machines owned by either of the two admin addresses.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fees: &amp;lt;fee_policy&amp;gt;&lt;/code&gt; specifies who pays for the registration and other fees. It can be either &lt;code&gt;endorsing_node&lt;/code&gt; when the node running the app pays, or &lt;code&gt;instance&lt;/code&gt; when the app instance pays.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final piece of this section is &lt;code&gt;machines&lt;/code&gt;, where the specific app deployment takes place. If you remember the &lt;strong&gt;&lt;a href="https://dev.to/dc600/roflize-an-app-part-2-create-build-deploy-test-2hmk"&gt;oasis rofl deploy&lt;/a&gt;&lt;/strong&gt; tutorial, it creates a new &lt;code&gt;default&lt;/code&gt; machine if there is no existing machine. If there is one, then the app is redeployed here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;machine_name&amp;gt;&lt;/code&gt; is the name you choose for the machine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;provider: &amp;lt;provider_address&amp;gt;&lt;/code&gt; is the Oasis native address of the ROFL provider hosting the machine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;offer: &amp;lt;offer_name&amp;gt;&lt;/code&gt; specifies what offer you have chosen.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;id: &amp;lt;machine_id&amp;gt;&lt;/code&gt; is the ID of the machine per provider.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permissions&lt;/code&gt; are optional, and when present, indicate ROFL scheduler-specific permissions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;log.view&lt;/code&gt; will list all the Oasis native addresses that can access machine logs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;code&gt;appd&lt;/code&gt; REST API&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Each containerized app running in ROFL runs a special daemon called &lt;code&gt;rofl-appd&lt;/code&gt;. It exposes additional functions via a simple HTTP REST API. To enable easier access isolation, the API is exposed via a UNIX socket located at &lt;code&gt;/run/rofl-appd.sock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's consider this example where we have used the &lt;a href="https://docs.docker.com/reference/compose-file/services/#short-syntax-5" rel="noopener noreferrer"&gt;short syntax for Compose volumes&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mycontainer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... other details omitted ...&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/run/rofl-appd.sock:/run/rofl-appd.sock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ROFL clients&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For your ROFL app, it is strongly recommended that you follow the steps to bind the UNIX socket by accessing the ROFL REST API through one of the ROFL clients. You can choose any one of the following languages.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;oasis-rofl-client&lt;/code&gt; for &lt;a href="https://pypi.org/project/oasis-rofl-client/" rel="noopener noreferrer"&gt;Python&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@oasisprotocol/rofl-client&lt;/code&gt; for &lt;a href="https://www.npmjs.com/package/@oasisprotocol/rofl-client" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;oasis-rofl-client&lt;/code&gt; for &lt;a href="https://github.com/oasisprotocol/oasis-sdk/tree/main/rofl-client/rs" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: Although the communication with &lt;code&gt;rofl-appd&lt;/code&gt; is through UNIX sockets, the REST service still uses the HTTP protocol. In our examples, we will be using the &lt;code&gt;http://localhost/&amp;lt;endpoint_path&amp;gt;&lt;/code&gt; format throughout. You are free to provide any name instead of a hostname.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Endpoints&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App Identifier&lt;/strong&gt; is where the endpoint is used to retrieve the app ID.&lt;br&gt;
Endpoint: &lt;code&gt;/rofl/v1/app/id&lt;/code&gt; (&lt;code&gt;GET&lt;/code&gt;)&lt;br&gt;
Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rofl1qqn9xndja7e2pnxhttktmecvwzz0yqwxsquqyxdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here, each registered app automatically gets access to a decentralized on-chain key management system. Now, the keys can only be generated inside properly attested app instances. They remain unchanged even if the app is deployed elsewhere, or even if its state is erased.&lt;br&gt;
Endpoint: &lt;code&gt;/rofl/v1/keys/generate&lt;/code&gt; (&lt;code&gt;POST&lt;/code&gt;)&lt;br&gt;
Example request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"demo key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"secp256k1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;key_id&lt;/code&gt; is used for domain separation of different keys. It is a unique identifier, with every key ID corresponding to a different key.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kind&lt;/code&gt; defines what kind of key should be generated. Options include:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;raw-256&lt;/code&gt; to generate 256 bits of entropy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;raw-386&lt;/code&gt; to generate 384 bits of entropy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ed25519&lt;/code&gt; to generate an Ed25519 private key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;secp256k1&lt;/code&gt; to generate a Secp256k1 private key, as used in our example&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The generated &lt;code&gt;key&lt;/code&gt; is returned as a hexadecimal string.&lt;br&gt;
Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a54027bff15a8726b6d9f65383bff20db51c6f3ac5497143a8412a7f16dfdda9"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Authenticated Transaction Submission&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is important if your app is registered with a different chain instead of Oasis. It enables your ROFL app to submit authenticated transactions to that chain. As these transactions are signed by an &lt;strong&gt;endorsed ephemeral key&lt;/strong&gt;, they get automatically authenticated.&lt;/p&gt;

&lt;p&gt;This also helps to easily authenticate the transaction origin in smart contracts by simply invoking an &lt;a href="https://api.docs.oasis.io/sol/sapphire-contracts/contracts/Subcall.sol/library.Subcall.html#roflensureauthorizedorigin" rel="noopener noreferrer"&gt;appropriate subcall&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Subcall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;roflEnsureAuthorizedOrigin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roflAppID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Endpoint: &lt;code&gt;/rofl/v1/tx/sign-submit&lt;/code&gt; (&lt;code&gt;POST&lt;/code&gt;)&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"encrypt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"gas_limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1234845aaB7b6CD88c7fAd9E9E1cf07638805b20"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dae1ee1f00000000000000000000000000000000000000000000000000002695a9e649b2"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's decipher the fields before proceeding further.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tx&lt;/code&gt; describes the transaction content. Different transaction kinds are supported as defined by the &lt;code&gt;kind&lt;/code&gt; field. &lt;/p&gt;

&lt;p&gt;Ethereum-compatible calls (&lt;code&gt;eth&lt;/code&gt;) use standard fields such as &lt;code&gt;gas_limit&lt;/code&gt;, &lt;code&gt;to&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, and &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;gas_limit&lt;/code&gt;, you can input a JSON number (as used in the example), a decimal string, or a &lt;code&gt;0x&lt;/code&gt;-prefixed hex string. There should not be any whitespace, and irrespective of the input, it will be interpreted as a non-negative 64-bit integer.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;value&lt;/code&gt;, you can input a JSON number up to &lt;code&gt;2^64 - 1&lt;/code&gt;, a decimal string, or a 0x-prefixed hex string. There should not be any whitespace in the string forms, and the value must represent a non-negative integer up to 256 bits.&lt;/p&gt;

&lt;p&gt;For hex-encoded fields such as &lt;code&gt;to&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt;, you can input strings with or without a leading &lt;code&gt;0x&lt;/code&gt; prefix, but there should not be any whitespace or prefix-only input. Empty strings are accepted for contract creation or empty calldata, e.g. &lt;code&gt;to: ""&lt;/code&gt; or &lt;code&gt;data: ""&lt;/code&gt;. If you are providing input for the &lt;code&gt;to&lt;/code&gt; field, it must decode to exactly 20 bytes representing an Ethereum address.&lt;/p&gt;

&lt;p&gt;Alternately, Oasis SDK calls (&lt;code&gt;std&lt;/code&gt;) support CBOR-serialized hex-encoded &lt;code&gt;Transactions&lt;/code&gt; to be specified.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;encrypt&lt;/code&gt; is a boolean flag specifying whether the transaction should be encrypted. This field is &lt;code&gt;true&lt;/code&gt; by default. When an ephemeral key is being used, the encryption is handled transparently for the caller, and any response is first decrypted before being passed on.&lt;/p&gt;

&lt;p&gt;Now, as the outcome of the example request, the example response inside &lt;code&gt;data&lt;/code&gt; is generated as a JSON response containing a CBOR-serialized hex-encoded &lt;a href="https://api.docs.oasis.io/rust/oasis_runtime_sdk/types/transaction/enum.CallResult.html" rel="noopener noreferrer"&gt;call result&lt;/a&gt; that you will need to deserialize.&lt;/p&gt;

&lt;p&gt;If the call result is successful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a1626f6b40"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It deserializes as &lt;code&gt;{"ok": ''}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If it is unsuccessful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a1646661696ca364636f646508666d6f64756c656365766d676d6573736167657272657665727465643a20614a416f4c773d3d"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It deserializes as &lt;code&gt;{"fail": {"code": 8, "module": "evm", "message": "reverted: aJAoLw=="}}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replica Metadata&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This allows apps to publish arbitrary key-value pairs included in the on-chain ROFL replica registration and automatically namespaced with &lt;code&gt;net.oasis.app&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Get Metadata&lt;/strong&gt;: With this, you can retrieve all user-set metadata key-value pairs.
Endpoint: &lt;code&gt;/rofl/v1/metadata&lt;/code&gt; (&lt;code&gt;GET&lt;/code&gt;)
Example response:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key_fingerprint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a54027bff15a8726"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Set Metadata&lt;/strong&gt;: With this, you can set metadata key-value pairs to replace all existing app-provided metadata. 
Endpoint: &lt;code&gt;/rofl/v1/metadata&lt;/code&gt; (&lt;code&gt;POST&lt;/code&gt;)
Example request:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key_fingerprint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a54027bff15a8726"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameters for metadata validation are the number of pairs, key size, and value size.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Upsert Metadata&lt;/strong&gt;: With this, you can input or update metadata key-value pairs. However, if you did not specify it in your request but there is existing app metadata, that will not be affected.
Endpoint: &lt;code&gt;/rofl/v1/metadata&lt;/code&gt; (&lt;code&gt;PUT&lt;/code&gt;)
Example request:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Delete Metadata&lt;/strong&gt;: With this, you can delete given metadata keys, while keys that no longer exist will be skipped.
Endpoint: &lt;code&gt;/rofl/v1/metadata&lt;/code&gt; (&lt;code&gt;DELETE&lt;/code&gt;)
Example request:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"key_fingerprint"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever you use Set, Upsert, or Delete Metadata, any change in the metadata triggers a registration refresh.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This runs arbitrary query methods defined in the &lt;a href="https://github.com/oasisprotocol/oasis-sdk/tree/main/runtime-sdk" rel="noopener noreferrer"&gt;Oasis Runtime SDK&lt;/a&gt; module and returns the result.&lt;/p&gt;

&lt;p&gt;Endpoint: &lt;code&gt;/rofl/v1/query&lt;/code&gt; (&lt;code&gt;POST&lt;/code&gt;)&lt;br&gt;
Example request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rofl.App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a16269645500694cb01f85408d624ea267f657bf285787a61db3"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;method&lt;/code&gt; refers to the internal name of query methods; in our example, it is &lt;a href="https://github.com/oasisprotocol/oasis-sdk/blob/394da333625a189abd8b752a9f2dc46bb883a781/runtime-sdk/src/modules/rofl/mod.rs#L647" rel="noopener noreferrer"&gt;rofl.App&lt;/a&gt;. You will recognize query methods by the &lt;code&gt;#[handler(query = "...")]&lt;/code&gt; annotation in the Oasis Runtime SDK source.&lt;br&gt;
&lt;code&gt;args&lt;/code&gt; represent query parameters for the method serialized as CBOR and hex-encoded.&lt;/p&gt;

&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"a76269645500ffe981cceff2d759d19fa926faebb7d90c0a59a56373656b582056c6d4841fa5ad24ad761088cb7053ad312ef13f3c2f405640fdba2bde4c14386561646d696e55007814f3d954f41b6459eb9e4bc8fbc6767ece5aa9657374616b658249056bc75e2d631000004066706f6c696379a56466656573026671756f746573a263696173f663706373a363746478a173616c6c6f7765645f7464785f6d6f64756c657380737463625f76616c69646974795f706572696f64181e781e6d696e5f7463625f6576616c756174696f6e5f646174615f6e756d6265721268656e636c6176657382a2696d725f7369676e6572582000000000000000000000000000000000000000000000000000000000000000006a6d725f656e636c6176655820bd4844a79a12ba365e890ddeaebbc4e4292797c7d956b42c2e25e4aefce3b124a2696d725f7369676e6572582000000000000000000000000000000000000000000000000000000000000000006a6d725f656e636c6176655820412c94a9baa0949f718dbba41ab89c38ea5c320345bba36b07e2ef857ffe2fb96c656e646f7273656d656e747381a163616e79a06e6d61785f65787069726174696f6e036773656372657473a26a50494e4154415f4a5754590327a462706b58207f88546291174f854a8ce2eb4bbfc8e62e40d60cdae2d600920a766d3006bf6c646e616d65581aad0460d0f742ad697b6d7c8462cc2b153deeb051a791553ef52b656e6f6e63654f8cbbe6631910d9a702e49bd30ee8f46576616c75655902c1352d823e54f75c846579066e2c1a750387f0630e3f29dba5524984712883bb33371ff017e507ae432b135312af64bfb85f3b17def05b2ac2744256f5accf1a26b29cd8cd412f08bfc9204f9bfa670b2d65972cfc4a8d4e2074402f21c18dfe554b1f0a8a731c077699f741807b3a4047ef4dc570958b8b46111a445259e93c9b92a5f72a23d32cbbef875efe586a8ddda38f1fa286d19b369a2022c3eae1cdbf6f6de4dc055bbab36a2c4830f8e2c64437f5f878f419e21f3a4c0f13c47b63697668b34722eaa61bdffa12e82be6d0266a41590254c9d70e9237475f6115c2867065c49afa8032acdfe0bc5dc671ef48ebc58d893937659243479e2eaa38815cd8665541e4c7e40349524cda15f2d410cba100ee27f0a59dc63534f7cff2444b57c7b74060cf8c3e21e1590b597384a89a463d6bb4a52fc52a4592889448a8f8e0c02fef1689c1efea58ddc08783f6d22d7a908cdf2a45bc46a79a3b73ff5f13bbbf7219973a7382eee84b3b4d48036b5e87fb24223e6387a3e37f9c1ac9722534adfef0201ec13db2e70fe9cd0336f020e50b59d7d32951378f568a4ef3a8117386ff0f1ba4b7d33dcf913daa696a6a7d64d20220b0e5eec994ea56aa9c01f56f5e12bf7d555b3f4a218ddbd8ae1586d5cb1e76802c90e26472b233686e8449284829378163acd77d1b65d4953a76cc497584580c1a5ac4fe6d97fd818fa53c2eb43c6f1b7a79211ef57f24036b1f8ed37f4c3d36873bbbd876769a5fde17add6926317afc96c9707e10b150735c63877ffd6475b1a27b6dd108940f0097375e422b1d308c6c8a0a83847368f5760778c54f2a70b44f9365c55c4b5d69341cad62d6fdb11aa25a9e26b4977adebd65718042bda1cbbf988298d293547107c2f5899352188179bc4d22febc66e8e351885498e707dee583d052c0b7c13f930e4529b59c36c20ee3ee6d29d1a3e2bb65bd489b7206cd45d2ae046f1e147d6407c166e494e465552415f4150495f4b45595899a462706b582074be2e227be81a5e35943ac1b79e238395b9bc367f7a0d1eed740c259ae23a37646e616d65581ee5190cda87688753f6f221890bfed8fe0e27b3ced4a9bc54537da1f4cd90656e6f6e63654fcf5411193abf4f4711f17179ea4b6f6576616c756558304675a29c8398bc94b5057063b4badeb9937a6e019ef7f8095d6b5a035106d4e8e7d710af9b6883848886481c1d180cbc686d65746164617461a7736e65742e6f617369732e726f666c2e6e616d656f76616c696461746f722d6167656e74756e65742e6f617369732e726f666c2e617574686f72782a4d61746576c5be204a656b6f766563203c6d617465767a406f6173697370726f746f636f6c2e6f72673e766e65742e6f617369732e726f666c2e6c6963656e73656a4170616368652d322e30766e65742e6f617369732e726f666c2e76657273696f6e65302e312e30776e65742e6f617369732e726f666c2e686f6d6570616765784f68747470733a2f2f6769746875622e636f6d2f6f6173697370726f746f636f6c2f6572632d383030342f626c6f622f6d61737465722f524541444d452e6d642376616c696461746f722d6167656e7478196e65742e6f617369732e726f666c2e7265706f7369746f7279782968747470733a2f2f6769746875622e636f6d2f6f6173697370726f746f636f6c2f6572632d38303034781a6e65742e6f617369732e726f666c2e6465736372697074696f6e787f4c697374656e7320746f2056616c69646174696f6e52657175657374206576656e7473206f6620746865204552432d383030342076616c69646174696f6e20726567697374727920616e642076616c696461746573207768657468657220746865206167656e7420697320706f776572656420627920524f464c205445452e"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;data&lt;/code&gt;, the JSON response contains the CBOR-serialized method's return value in hex format.&lt;/p&gt;

&lt;p&gt;If you want to try other examples, you can check out the &lt;a href="https://github.com/oasisprotocol/demo-rofl/blob/ab7e60aeb5f10aaec0a5f401086b2ba259a30107/docker/app.sh#L9-L18" rel="noopener noreferrer"&gt;relevant section&lt;/a&gt; of the ROFL demo repository for querying with curl directly.&lt;br&gt;
There is also a production-ready Python example at hand - in the  &lt;a href="https://github.com/oasisprotocol/erc-8004/blob/18f8630f7397ec889ea55b008391664f3b736128/rofl-8004/rofl_metadata.py#L47" rel="noopener noreferrer"&gt;ROFL-8004 implementation&lt;/a&gt; where the query endpoint is used to fetch various app on-chain metadata for registration in the &lt;a href="https://eips.ethereum.org/EIPS/eip-8004#identity-registry" rel="noopener noreferrer"&gt;ERC-8004 identity registry&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Port Proxy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When you publish a port in your &lt;code&gt;compose.yaml&lt;/code&gt; file, the ROFL proxy automatically makes your services accessible via public URLs. It also ensures the routed traffic is done correctly.&lt;/p&gt;

&lt;p&gt;This uses TLS, which is terminated inside your ROFL enclave, maintaining confidentiality and integrity protection. As a result, even the provider cannot see or modify the traffic. Moreover, the default &lt;code&gt;terminate-tls&lt;/code&gt; mode generates and configures a Let's Encrypt certificate in ROFL to authenticate your services.&lt;/p&gt;

&lt;p&gt;To enable the proxy and expose a port from your container, you need to publish it in your &lt;code&gt;compose.yaml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;compose.yaml&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.io/hashicorp/http-echo:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5678:5678"&lt;/span&gt; &lt;span class="c1"&gt;# Expose container port 5678 on host port 5678&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After deploying your app, you can find the generated URL by running the usual command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl machine show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output generated in this way will show a &lt;code&gt;Proxy&lt;/code&gt; section with the public URL for each published port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;m602.test-proxy-b.rofl.app&lt;/span&gt;
  &lt;span class="na"&gt;Ports from compose file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;5678 (frontend)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://p5678.m602.test-proxy-b.rofl.app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use the &lt;a href="https://docs.docker.com/reference/compose-file/services/#annotations" rel="noopener noreferrer"&gt;annotations&lt;/a&gt; in your &lt;code&gt;compose.yaml&lt;/code&gt; file to configure the proxy behavior.&lt;/p&gt;

&lt;p&gt;The general format of an annotation is &lt;code&gt;net.oasis.proxy.ports.&amp;lt;published_port&amp;gt;.&amp;lt;setting&amp;gt;: &amp;lt;value&amp;gt;&lt;/code&gt;.&lt;br&gt;
Here, &lt;code&gt;&amp;lt;published_port&amp;gt;&lt;/code&gt; is the external port exposed in your compose.yaml, and &lt;code&gt;&amp;lt;setting&amp;gt;&lt;/code&gt; indicates the specific proxy configuration like &lt;code&gt;mode&lt;/code&gt; or &lt;code&gt;custom_domain&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
Here I will configure port 80 to use the default &lt;code&gt;terminate-tls&lt;/code&gt; mode with a custom domain and port 8080 to use TCP &lt;code&gt;passthrough&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;compose.yaml&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;myservice&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.io/my/service:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:8080"&lt;/span&gt;
    &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;net.oasis.proxy.ports.80.custom_domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydomain.com&lt;/span&gt;
      &lt;span class="na"&gt;net.oasis.proxy.ports.8080.mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;passthrough&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The application container exposes ports 80 and 8080.&lt;/li&gt;
&lt;li&gt;On port 80, the proxy terminates TLS for mydomain.com and forwards traffic to the application container.&lt;/li&gt;
&lt;li&gt;On port 8080, the proxy forwards the raw TCP connection to your application container (&lt;code&gt;mode: passthrough&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Annotation Reference&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;net.oasis.proxy.ports.&amp;lt;published_port&amp;gt;.mode&lt;/code&gt; defines how the proxy should handle connections for the specified port.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5or3r6as0y9qy9nl8o1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5or3r6as0y9qy9nl8o1i.png" alt=" " width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;net.oasis.proxy.ports.&amp;lt;published_port&amp;gt;.custom_domain&lt;/code&gt; assigns a custom domain name to the published port.&lt;/p&gt;

&lt;p&gt;Here, when using the default &lt;code&gt;terminate-tls&lt;/code&gt; mode, you need to use special configuration for your custom domain to route through the proxy. Once the app is deployed, you can use Oasis CLI for instructions to configure &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;TXT&lt;/code&gt; records in your DNS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl machine show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;m897.opf-testnet-rofl-25.rofl.app&lt;/span&gt;
  &lt;span class="na"&gt;Ports from compose file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;5678 (frontend)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://demo.rofl.build&lt;/span&gt;
      &lt;span class="s"&gt;* Point the A record of your domain to&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;131.153.241.25&lt;/span&gt;
      &lt;span class="s"&gt;* Add a TXT record to your domain&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;span class="s"&gt;oasis-rofl-verification=4SKHCn4E2SNDB5tXayQeHZsvH/+kJSNGuQaTAPepYJc=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you choose to go with &lt;code&gt;passthrough&lt;/code&gt; mode, the proxy will not terminate TLS and your app will then need to handle it directly. Also, here the &lt;code&gt;custom_domain&lt;/code&gt; setting is not needed, so you can configure the domain directly to the ROFL instance's address.&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;ignore&lt;/code&gt; mode, the port isn't published, so the &lt;code&gt;custom_domain&lt;/code&gt; setting has no effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Troubleshooting&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here I will cover some common errors and the troubleshooting process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compilation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes you will see an error message if the &lt;code&gt;aes&lt;/code&gt; and &lt;code&gt;ssse3&lt;/code&gt; compiler flags are not enabled during compilation of your SGX and TDX-raw ROFL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;error: The following target_feature flags must be set: +aes,+ssse3.
&lt;/span&gt;&lt;span class="gp"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/deoxysii-0.2.4/src/lib.rs:26:1
&lt;span class="go"&gt;|
&lt;/span&gt;&lt;span class="gp"&gt;26 | compile_error!("The following target_feature flags must be set: +aes,+ssse3.");&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workaround is to add default flags to your &lt;code&gt;.cargo/config.toml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[build]&lt;/span&gt;
&lt;span class="py"&gt;rustflags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;"target-feature&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;+aes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;+ssse&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="s"&gt;"]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;rustdocflags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;"target-feature&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;+aes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;+ssse&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="s"&gt;"]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;test&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;rustflags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;"target-feature&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;+aes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;+ssse&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="s"&gt;"]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;rustdocflags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;"target-feature&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;+aes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;+ssse&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="s"&gt;"]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Compose file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A couple of errors are possible here due to an upstream &lt;a href="https://github.com/containers/podman-compose/issues/264" rel="noopener noreferrer"&gt;&lt;code&gt;podman compose&lt;/code&gt; bug&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first is when environment variables defined are not considered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;oracle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CONTRACT_ADDRESS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0x5FbDB2315678afecb367f032d93F642f64180aa3&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/bin/sh -c 'python main.py $${CONTRACT_ADDRESS}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this type of error, the &lt;code&gt;CONTRACT_ADDRESS&lt;/code&gt; field will return as empty in ROFL. You need to inject the variable value directly inside &lt;code&gt;entrypoint&lt;/code&gt; as a workaround.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;oracle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/bin/sh -c 'python main.py 0x5FbDB2315678afecb367f032d93F642f64180aa3'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other type of error that may occur is when &lt;code&gt;depends_on&lt;/code&gt; is ignored.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contracts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ghcr.io/foundry-rs/foundry:latest"&lt;/span&gt;
    &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./contracts:/contracts&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/bin/sh -c 'cd contracts &amp;amp;&amp;amp; forge create'&lt;/span&gt;

  &lt;span class="na"&gt;oracle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/bin/sh -c 'python main.py'&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;on-failure&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contracts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service_completed_successfully&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this type of error, instead of &lt;code&gt;oracle&lt;/code&gt; spinning up once the &lt;code&gt;contracts&lt;/code&gt; service successfully deploys the contracts and finishes, they start in parallel by ignoring the &lt;code&gt;depends_on&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;There is no immediate workaround as of now. You can try to implement customized logic in your &lt;code&gt;oracle&lt;/code&gt; service to crash it, and then trigger the restart mechanism and try again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;appd&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you encounter the &lt;code&gt;422 Unprocessable Entity&lt;/code&gt; error, when the provided request couldn't be decoded, you need to ensure all the required fields are present and correctly formatted in accordance with the &lt;strong&gt;&lt;code&gt;appd&lt;/code&gt; REST API&lt;/strong&gt; section described above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ROFL Proxy URL is not working&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes the app might be using outdated artifacts, which will result in the proxy URL returned by &lt;code&gt;oasis rofl machine show&lt;/code&gt; being inaccessible. This is easily fixed by updating to the latest Oasis CLI version. The next step is to run &lt;code&gt;oasis rofl upgrade&lt;/code&gt; in your project directory to update the artifacts in your &lt;code&gt;rofl.yaml&lt;/code&gt; file, and finally, rebuild and redeploy your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl build
oasis rofl update
oasis rofl deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This concludes our 2-part bonus guide describing the various features for your ROFL app, and some common troubleshooting hacks. Looking forward to your feedback in the comments section. &lt;/p&gt;

&lt;p&gt;For technical specs, APIs, architecture, and integration guides, the &lt;strong&gt;&lt;a href="https://docs.oasis.io/" rel="noopener noreferrer"&gt;Oasis documentation&lt;/a&gt;&lt;/strong&gt; is your starting point.&lt;br&gt;
For direct support on specific issues, the Oasis engineering team is available in the &lt;strong&gt;&lt;a href="https://discord.com/invite/BQCxwhT5wS" rel="noopener noreferrer"&gt;dev-central channel&lt;/a&gt;&lt;/strong&gt; on the official Discord.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>blockchain</category>
      <category>tee</category>
      <category>devex</category>
    </item>
    <item>
      <title>Blockchain Interoperability, Decoded. And What Lies Ahead.</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Thu, 23 Jul 2026 10:23:00 +0000</pubDate>
      <link>https://dev.to/dc600/blockchain-interoperability-decoded-and-what-lies-ahead-3ek</link>
      <guid>https://dev.to/dc600/blockchain-interoperability-decoded-and-what-lies-ahead-3ek</guid>
      <description>&lt;p&gt;Demystifying the intricacy of blockchain technology has been going on for decades now, and you would think we have come far enough to simplify the basic mechanics. Mostly true, but when a fundamental question like connectivity comes up, we are still trying to hone a universal hack for interoperability. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem Of Chains In Silo&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The blockchain space is teeming with networks, and most of them are built to be self-sufficient, deterministic, and siloed. This isolation in the distributed ledger technology is a deliberate design to insulate the networks from total damage should one of them break down.   &lt;/p&gt;

&lt;p&gt;This system assures safety, but comes with the inherent flaw of fragmentation, which hugely limits the scope of the technology. If Ethereum does not know what is going on over at Solana, it not only creates a bottleneck in data movement but also leaves liquidity stuck. The value of any asset will depreciate if it can only move inside the home chain. You need to be able to transfer your tokens across networks. Hence, we need protocol interoperability. &lt;/p&gt;

&lt;p&gt;Moving away from monolithic to modular blockchain architecture was one of the first steps. The advent of layer-2 networks, optimistic rollups, and sidechains could only address scalability but they hardly solved the data and value transfer proposition.  &lt;/p&gt;

&lt;p&gt;The cost of communication to enable this was one of the biggest pain points of the last decade - transactional overheads in the form of gas fees piling up, sometimes making fund transfers too expensive to be viable. Many of us have experienced this firsthand. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Building Bridges For Seamless Connection&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Over the years, we have seen breakthroughs in the interoperability situation- from cross-chain bridge iterations to, most recently, chain abstraction. Bridging your assets can either take the lock and mint route or the more fine-tuned atomic swap method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lock and mint&lt;/strong&gt; process, or its variation of &lt;strong&gt;burn and mint&lt;/strong&gt; process, works like this. Assets are locked (or burned) on the source chain, and identical value assets are created or minted on the destination chain.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kbg7fctof9vh6b79u2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kbg7fctof9vh6b79u2d.png" alt=" " width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;atomic swap&lt;/strong&gt; process, trustless cross-chain bridges, governed by smart contracts, are used. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgohlwg8eflckx532a6ij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgohlwg8eflckx532a6ij.png" alt=" " width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bridging, whether you go with a human-dependent model (multisig) or a trust-logic model (on-chain light client), has its own set of challenges. These bridges simply need to be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;trustless (existence of any external federated group of administrators could mean lost decentralization and exposure to hacking risks)&lt;/li&gt;
&lt;li&gt;extensible (adaptability of one protocol to another network’s domain)&lt;/li&gt;
&lt;li&gt;generalizable (capability to access and process all cross-domain datasets)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bottom line is there is always a trade-off. &lt;/p&gt;

&lt;p&gt;Bridges that are safe to use extract the cost of security as gas fees, and those that are cheap have high vulnerabilities leading to potential loss of your funds. &lt;/p&gt;

&lt;p&gt;As our DeFi footprint increases, hackers exploiting bridges have been a regular risk, with several hundred million user funds falling prey (&lt;a href="https://www.youtube.com/watch?v=G1SHHt5-Cms&amp;amp;t=320s" rel="noopener noreferrer"&gt;The Fragility Report&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=hlNNzUdPeCg&amp;amp;t=26s" rel="noopener noreferrer"&gt;The Mass Extinction Event&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;The time has come to talk about privacy now, and we will take a look at &lt;strong&gt;Oasis Privacy Layer (OPL)&lt;/strong&gt; and &lt;strong&gt;runtime off-chain logic (ROFL)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpsay4lp4spayu80mgrox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpsay4lp4spayu80mgrox.png" alt=" " width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Privacy As A Solution&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The gap left by the Bridging Trilemma - safe or cheap, rarely both - is where &lt;a href="https://oasis.net/" rel="noopener noreferrer"&gt;Oasis&lt;/a&gt; comes into the discussion. &lt;/p&gt;

&lt;p&gt;As a layer-1, PoS protocol with confidential computing and verifiable privacy as foundational premises, Oasis designed OPL, powered by the network's confidential EVM runtime, Sapphire, as an on-chain, plug-and-play interoperability tool. &lt;/p&gt;

&lt;p&gt;OPL is curated to ease developer activity, enabling cross-chain communication without migration. It bridges confidentiality to dApps living entirely on other chains through message-passing bridges. The dApp's main logic stays exactly where it is, gas token and all. Only the privacy-sensitive parts of execution get routed to Sapphire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmbrkkuenzs1o3fl0lx3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmbrkkuenzs1o3fl0lx3h.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What you get as a user out of this arrangement is confidential cross-chain transactions. No background tech distracting your experience, nor your financial privacy being accessible publicly in the name of full transparency. &lt;/p&gt;

&lt;p&gt;Compared to Polkadot's parachains or Cosmos's IBC at the network level, or even bridge protocols such as LayerZero and Axelar, this has a distinct point of difference. While the others solve the interoperability challenge with composability and stop at data (and value) movement, Oasis asks and answers the next logical question: whether this data should be visible once it does, and adds a privacy-preserving layer as a solution. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Off-chain Alternative&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After multisig, light client, and OPL, we now have a new approach- the Trustless AWS model. It involves secure and verifiable computation while moving the heavy lifting of verification off-chain. Oasis ROFL framework is a step in this direction. &lt;/p&gt;

&lt;p&gt;ROFL retains the black-box or secure enclave approach of OPL, using Trusted Execution Environments (TEEs) like Intel SGX or TDX. The architecture and the workflow promise optimal performance for running tamper-proof code and private, secure data processing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl4px8vn92lf6z39o5mm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl4px8vn92lf6z39o5mm1.png" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp794qedy6nkmvsca9zti.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp794qedy6nkmvsca9zti.jpeg" alt=" " width="680" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, Oasis can provide Privacy-as-a-Service to other chains by aligning ROFL with OPL. This means we can enjoy confidential bridging that combines multisig-grade trust with light-client-grade security, especially with cost efficiency that zero-knowledge proofs (ZKPs) lack. As cross-chain architectures, both ZKPs and even optimistic verification models also come up short in terms of built-in privacy capabilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl9mmytsa9xhygjfxq3r7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl9mmytsa9xhygjfxq3r7.png" alt=" " width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, what sets ROFL apart from everything else that came before is that it opens a door that bridges were never designed for: confidential, cross-chain intents. This is the basis for private swaps. Here, you can specify the condition that must be met before a swap executes. With enclave-held keys and the swap order sitting in the enclave memory until the moment of execution, it is structurally resistant to manipulation or front-running of the transaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Road Ahead&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The thread of our discussion inevitably leads to a conundrum. As interoperability options evolve, bridges can be faster, cheaper, safer, on-chain or off-chain, and still have a ceiling to what they can achieve. A single wallet achieved through chain abstraction might be the way to go.&lt;/p&gt;

&lt;p&gt;Consider this: a ROFL enclave holding a private key for any chain. It would mean signing a single transaction on Oasis while the matching action executes on Bitcoin or Ethereum or Solana or any protocol of your choice, without ever touching any of those networks directly. Here, you get smooth UI and UX, and the complexity is not your concern.&lt;/p&gt;

&lt;p&gt;Does this mean we have solved interoperability? No. But we have redefined the problem we started with. Moving data and assets across chains is doable and done. Now, we examine the mechanics of moving trust itself, verifiably and cheaply, without giving up confidentiality. That's where I think the road goes next. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://oasisrose.garden/lessons/blockchain-interoperability/" rel="noopener noreferrer"&gt;Blockchain Interoperability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://oasisrose.garden/lessons/the-future-of-interoperability/" rel="noopener noreferrer"&gt;The Future of Interoperability&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blockchain</category>
      <category>interoperability</category>
      <category>bridges</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Verifiable DeFi Is Catching On. Case Studies: Robin Markets, Tradable.</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Tue, 21 Jul 2026 09:54:51 +0000</pubDate>
      <link>https://dev.to/dc600/verifiable-defi-is-catching-on-case-studies-robin-markets-tradable-2cc1</link>
      <guid>https://dev.to/dc600/verifiable-defi-is-catching-on-case-studies-robin-markets-tradable-2cc1</guid>
      <description>&lt;p&gt;Confidential decentralized finance (DeFi) has always been one of the best use cases for Oasis's privacy stack. The industry's first and only production-ready confidential EVM, &lt;a href="https://oasis.net/blog/the-oasis-privacy-layer-powered-by-sapphire" rel="noopener noreferrer"&gt;Sapphire&lt;/a&gt;, was, however, only half the solution for trustless applications to ensure user data is sovereign and secured by default. &lt;/p&gt;

&lt;p&gt;On-chain runtime can only take you so far, especially when processing huge datasets or sensitive information is concerned. Oasis has crossed that hurdle now with runtime off-chain logic &lt;a href="https://oasis.net/blog/rofl-mainnet-launch" rel="noopener noreferrer"&gt;ROFL&lt;/a&gt; in production. This framework runs off-chain compute inside a Trusted Execution Environment (TEE) before handing over the result to Sapphire for on-chain storage and finalization. &lt;/p&gt;

&lt;p&gt;As Sapphire and ROFL enable verifiable privacy at scale, thereby counteracting the trust bottleneck, several projects have aligned themselves with Oasis to integrate this privacy layer for their products. Here, I will outline two examples that offer a glimpse into the future where confidential DeFi unfolds as verifiable private DeFi of tomorrow, uplifting user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Robin Markets &amp;amp; verifiable yield with trustless oracle&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Prediction markets are an interesting spin-off of the DeFi space, and Polymarket is undeniably one of the biggest players. Here, users can bet on real-world scenarios and outcomes, from elections to sports to just anything that involves Yes/No decisions. They can buy YES or NO tokens that are essentially tokenised positions in the market. The potentially lucrative returns attract not only crypto-native but also mainstream users, and at any given time, hundreds of millions in positions are open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Funds locked with idle positions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The prediction market sounds fun and simple to engage with but has an inherent problem. When a user buys those YES or NO tokens, the time taken to resolve the position may range from a few hours to a few days to a few months. And until resolution, the funds are locked in the position, sitting idle, and with zero benefit to the asset owner. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://robin.markets/" rel="noopener noreferrer"&gt;Robin Markets&lt;/a&gt; proposes to solve this inefficient situation. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftsq1w8t8lf6sgmzjs5bv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftsq1w8t8lf6sgmzjs5bv.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Users can trade and stake the YES or NO tokens, and earn passive income. It works like this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Robin Markets pairs the YES and NO tokens&lt;/li&gt;
&lt;li&gt;Then finds a YES staker and a NO staker on the same market&lt;/li&gt;
&lt;li&gt;Next pulls the underlying USDC collateral from Polymarket&lt;/li&gt;
&lt;li&gt;Finally routes it into viable DeFi yield strategies
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhdg0b82xht4u1uauep27.png" alt=" " width="800" height="398"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this scenario, both the YES and NO stakers stay in the market with their open positions untouched, while the collateral helps earn them APY.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yield distribution mechanism&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Users earning from idle positions is good news, but the yield distribution scenario is challenging. At the resolution point, one position wins, and the other loses. But the yield accumulated during the lifecycle of the positions is not equivalent for the opposing parties, representing variable risks. &lt;/p&gt;

&lt;p&gt;It is improbable that the YES and NO stakers split the risk and the position 50:50, so the yield payout also cannot be an even distribution. Splitting the yield at the final resolved price is also inaccurate, as it will nullify the changing positions during the lifecycle of the staking period. &lt;/p&gt;

&lt;p&gt;Time-weighted average, or TWAP, is used to solve this dilemma. This mechanism tracks the average price of both the YES and NO positions during the lifecycle of the staking period before calculating yield distribution. Robin Markets has a trustless oracle server to access the price history from Polymarket. It then uses TWAP to process the yield calculation, and signs the results on-chain. Any update on the yield in the staking vault only applies when a valid signature is verified from the oracle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Oasis role&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The trustless oracle runs on ROFL, executing the whole process of price fetching, TWAP computation, and result sign-off inside a secure enclave. No part of the process is visible, accessible, or modifiable by Robin Markets or any third parties. Also, since on-chain verification of signature must accompany any update, it ensures the oracle data remains in sync with the current chain state.&lt;/p&gt;

&lt;p&gt;The verifiable-by-design computation and tamper-proof oracle reports ensure there are no trust gaps in the mechanism, letting users avail a first for yield on locked prediction-market positions.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Tradable &amp;amp; verifiable market intelligence&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;DeFi is the go-to web3 use case for many, but the market reality of retail traders versus institutions and professional traders shows a huge and unfair gap. While institutions benefit from reading and interpreting on-chain flows, liquidity conditions, and real-time market sentiments, professional traders have access to high-grade tools, automations, and data analysis and insights. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://tradable.app/" rel="noopener noreferrer"&gt;Tradable platform&lt;/a&gt; and its SenseAI tool help plug this imbalance. With automated trading enabled and a personalised AI portfolio assistant to help, users other than traditional heavy hitters can also make the most of the market opportunities.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxrz0agktcqhqfjkycs5j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxrz0agktcqhqfjkycs5j.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an autonomous agent, SenseAI reads the market 24x7, bringing institutional feeds and insights to retail. It involves simultaneous access to three layers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Macro structures like dominance trends and ETF flows&lt;/li&gt;
&lt;li&gt;Network health like wallet data and capital inflows/ outflows&lt;/li&gt;
&lt;li&gt;Market sentiment like fear/ greed cycles, narrative buildup, and trajectory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With institutional-grade intelligence on their fingertips, average users can use the opportunity to translate market trends and signals into potentially high-return crypto portfolios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mechanics of SenseAI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SenseAI, as a market intelligence tool, differs from most similar solutions that produce information overload by dumping too much raw data, with users unable to decide how to interpret the signals or what to do next. Instead, it runs a process that combines reasoned output from strategy, research, and analysis.&lt;/p&gt;

&lt;p&gt;As a result, SenseAI is involved in context building to decide what matters and when, data access and processing, and using all this to analyse signals and infer the best foot forward. Two key components of the process are &lt;strong&gt;divergence&lt;/strong&gt; and &lt;strong&gt;confluence&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Divergence&lt;/strong&gt; is where the tool can flag the fragility of a network even when the price pumps and no apparent weakness is visible or predicted by price action. &lt;strong&gt;Confluence&lt;/strong&gt; is where the tool can read signal over narrative so that liquidity and on-chain activity expansion is validated as real strength rather than mere hype.&lt;/p&gt;

&lt;p&gt;Every insight is encrypted, verified and paid on-chain, yet the whole process feels like a normal web request.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0tn0y5iecllhmf5yz7ox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0tn0y5iecllhmf5yz7ox.png" alt=" " width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Oasis role&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Market analysis, especially using autonomous agents, needs integrity, and that trust must be earned. The mechanism should be tamper-proof, and there should also be no bias for or against any crypto assets. Running inside ROFL, SenseAI ensures confidential compute on the Tradable virtual chain on Aurora. With &lt;a href="https://oasis.net/blog/tees-remote-attestation-process" rel="noopener noreferrer"&gt;remote attestation&lt;/a&gt; securing the tool's mechanism, it is safe from any manipulation by the operator, and the user prompts also stay confidential. &lt;/p&gt;

&lt;p&gt;Like any other AI tool, memory is the eternal pain point. As user interactions grow, memory also grows, branches, and needs constant access for context. The storage problem is solved by putting the entire memory, comprising messages and context, in an encrypted file on Autonomys Auto Drive. So, the confidential on-chain smart contract gatekeeps and proves any conversation that happens; Auto Drive stores the conversation content, and only the user, holding the keys, can access and read it.&lt;/p&gt;

&lt;p&gt;Currently, SenseAI is in testnet mode, where usage by the community provides the information layer for the tool. After mainnet rollout on Aurora and enabling of live token payments, it will be integrated into the Tradable platform as the verifiable market intelligence for individual traders.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Final words&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Robin Markets and Tradable's SenseAI showcase how next-gen confidential DeFi evolves alongside AI agents. Integrating Oasis's tech stack like ROFL underlines the value of off-chain compute and verifiable privacy.&lt;/p&gt;

&lt;p&gt;What is your take on these projects? Let's hit the comments section.&lt;br&gt;
Also, explore Oasis's in-house &lt;a href="https://oasis.net/solutions-defi" rel="noopener noreferrer"&gt;private DeFi&lt;/a&gt; solution, Privana, or how the protocol can help build and deploy &lt;a href="https://oasis.net/ai-agents" rel="noopener noreferrer"&gt;verifiable agents&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>decentralizedfinance</category>
      <category>privacy</category>
      <category>verifiability</category>
    </item>
    <item>
      <title>ROFLize an App: Bonus Guide to Features &amp; Troubleshooting (Part 1)</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Fri, 17 Jul 2026 08:11:12 +0000</pubDate>
      <link>https://dev.to/dc600/roflize-an-app-bonus-guide-to-features-troubleshooting-part-1-324d</link>
      <guid>https://dev.to/dc600/roflize-an-app-bonus-guide-to-features-troubleshooting-part-1-324d</guid>
      <description>&lt;p&gt;Earlier, I described the entire workflow of how to ROFLize an app, from &lt;a href="https://dev.to/dc600/roflize-an-app-part-1-rofl-workflow-to-initialization-4m78"&gt;setting up prerequisites&lt;/a&gt; to &lt;a href="https://dev.to/dc600/roflize-an-app-part-2-create-build-deploy-test-2hmk"&gt;testing&lt;/a&gt; it. In a 2-part addendum, I will take you through the various features of ROFL that enhance the apps using it, and also how to troubleshoot issues. The first part covers the first three features.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ROFL Marketplace&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While outlining the deployment process of the workflow, I first mentioned the ROFL marketplace. So, what is it? The ROFL marketplace is an on-chain protocol designed for app developers and ROFL node providers. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6oqhgj6sujlj68mnqhlz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6oqhgj6sujlj68mnqhlz.png" alt=" " width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the diagram shows, the ROFL marketplace has three entities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;App developers&lt;/strong&gt;: They build an app, register it on-chain, and rent a machine from the ROFL provider to deploy their apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ROFL providers&lt;/strong&gt;: They are the on-chain entity that bills and assigns machines to the developers, with a hosting plan called the offer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ROFL nodes&lt;/strong&gt;: These are servers running on the Oasis node that instantiate machines for hosting an app.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are an app developer, refer to the 2-part workflow series, and the deployment process in Part 2 will be relevant for you. Or, if you approach this as an ROFL provider, start by learning about the &lt;a href="https://docs.oasis.io/node/run-your-node/rofl-node/" rel="noopener noreferrer"&gt;ROFL node&lt;/a&gt; and setting it up to execute runtime off-chain logic inside a TEE.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Secrets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes we encounter situations where containers need to access data, but exposing it would be disastrous. API keys for accessing certain services fall into this category, and blockchain transparency cannot prevent them from becoming public. Containers running in ROFL can safely pass this type of data using the &lt;strong&gt;secrets&lt;/strong&gt; feature.&lt;/p&gt;

&lt;p&gt;Secrets are arbitrary key-value pairs powered by end-to-end encryption, which can only be decrypted inside an app with the right attestation. You can manage this feature using the Oasis CLI, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"my very secret value"&lt;/span&gt; | oasis rofl secret &lt;span class="nb"&gt;set &lt;/span&gt;mysecret -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a detailed understanding of secret management commands, including importing from &lt;strong&gt;.env&lt;/strong&gt; files, removing secrets, and other advanced features, check out the &lt;a href="https://docs.oasis.io/build/tools/cli/" rel="noopener noreferrer"&gt;CLI documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the above example, the &lt;strong&gt;mysecret&lt;/strong&gt; we created is only encrypted and updated in the local app manifest file, and not yet reflected in the full app version. This enables you to configure multiple secrets without constantly updating the on-chain app configuration. Once you have created all the secrets you need, you can update them all at once with the usual command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The local app manifest doesn't need to be private while storing the secrets. The secret values inside the manifest are end-to-end encrypted. In effect, they are completely inaccessible, even to the administrator who set them up. The reason why only the app can decrypt the secret is that every time a new secret is created, it is encrypted with a corresponding new ephemeral key. As soon as encryption is done, the ephemeral key is discarded and irretrievable. &lt;/p&gt;

&lt;p&gt;Now, the secrets pass inside the ROFL containers in two ways.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Environment Variables&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each secret is automatically exposed in the Compose environment and can be trivially used in the Compose file. When this happens, the secret name convention changes, using capitalization and underscores. For example, the earlier known &lt;strong&gt;mysecret&lt;/strong&gt; will now become &lt;strong&gt;MYSECRET&lt;/strong&gt;. However, if you use any space in the name, e.g., &lt;strong&gt;my secret&lt;/strong&gt;, it will become &lt;strong&gt;MY_SECRET&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.io/library/alpine:3.21.2@sha256:f3240395711384fc3c07daa46cbc8d73aa5ba25ad1deb97424992760f8cb2b94&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "Hello $MYSECRET!"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MYSECRET=${MYSECRET}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Container Secrets&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each secret is also defined and can be passed as a container secret as per &lt;a href="https://docs.docker.com/compose/how-tos/use-secrets/" rel="noopener noreferrer"&gt;Docker documentation&lt;/a&gt;. You will also need to define this as an external secret since it is created by the app during boot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker.io/library/alpine:3.21.2@sha256:f3240395711384fc3c07daa46cbc8d73aa5ba25ad1deb97424992760f8cb2b94&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "Hello $(cat /run/secrets/mysecret)!"&lt;/span&gt;
    &lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysecret&lt;/span&gt;

&lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mysecret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Persistent Storage&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.oasis.io/build/sapphire/" rel="noopener noreferrer"&gt;Sapphire's&lt;/a&gt; confidential EVM runtime enables ROFL developers to use smart contracts for secure and consistent storage. But this is not workable for apps with intensive read/write functions. That's why ROFL has built-in support for local persistent storage. This feature comes with these characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local per-machine storage, not synchronized across other ROFL replicas&lt;/li&gt;
&lt;li&gt;Fully encrypted on the host machine&lt;/li&gt;
&lt;li&gt;Preserved during ROFL upgrades and node restarts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the key benefits of this feature is its utility for caching. Whenever the &lt;strong&gt;compose.yaml&lt;/strong&gt; file defines Docker images, persistent storage becomes the default storage destination. They are fetched only the first time an app is deployed, and afterwards, a cached version is used.&lt;/p&gt;

&lt;p&gt;Another aspect of the feature is that all non-external container volumes will automatically reside in persistent storage. Let me illustrate this with an example. Here, I have defined a new volume, as referenced in &lt;a href="https://docs.docker.com/reference/compose-file/volumes/" rel="noopener noreferrer"&gt;Docker documentation&lt;/a&gt;. I have named it &lt;strong&gt;my-volume&lt;/strong&gt; and made &lt;strong&gt;.ollama&lt;/strong&gt; in the home folder persistent. As a result, every time a machine hosting the app restarts, I will not need to download ollama models.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;compose.yaml&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ollama&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docker.io/ollama/ollama"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;11434:11434"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;my-volume:/root/.ollama&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/bash"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-c"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/bin/ollama&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;serve&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sleep&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ollama&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pull&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;deepseek-r1:1.5b;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;wait"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;my-volume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;a href="https://dev.to/dc600/roflize-an-app-bonus-guide-to-features-troubleshooting-part-2-2j2c"&gt;concluding part&lt;/a&gt; of this addendum guide, I will discuss the remaining features and troubleshooting process.&lt;/p&gt;

&lt;p&gt;For technical specs, APIs, architecture, and integration guides, the &lt;strong&gt;&lt;a href="https://docs.oasis.io/" rel="noopener noreferrer"&gt;Oasis documentation&lt;/a&gt;&lt;/strong&gt; is your starting point. &lt;br&gt;
For direct support on specific issues, the Oasis engineering team is available in the &lt;strong&gt;&lt;a href="https://discord.com/invite/BQCxwhT5wS" rel="noopener noreferrer"&gt;dev-central channel&lt;/a&gt;&lt;/strong&gt; on the official Discord. &lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>blockchain</category>
      <category>tee</category>
      <category>devex</category>
    </item>
    <item>
      <title>ROFLize an App? Part 2: Create, Build, Deploy, Test</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Wed, 15 Jul 2026 07:48:55 +0000</pubDate>
      <link>https://dev.to/dc600/roflize-an-app-part-2-create-build-deploy-test-2hmk</link>
      <guid>https://dev.to/dc600/roflize-an-app-part-2-create-build-deploy-test-2hmk</guid>
      <description>&lt;p&gt;Continuing with the 2-part series that is designed to guide developers as they attempt to ROFLize an app, we have &lt;a href="https://dev.to/dc600/roflize-an-app-part-1-rofl-workflow-to-initialization-4m78"&gt;so far covered&lt;/a&gt; the workflow, the prerequisites needed to proceed, how to containerize the app, and initialize. &lt;br&gt;
In this concluding part of the series, I will show you how to create, build, deploy, and test the app.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Create&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The first step for building an app is to create on-chain and assign a unique identifier or app ID. This ID is for use by on-chain smart contracts and has two functions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;helps interact with the right app&lt;/li&gt;
&lt;li&gt;gives the app access to a decentralized key management system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To create an app, you will need enough funds. Currently, the threshold for creating a ROFL app is 100 tokens. &lt;br&gt;
If you are doing this on mainnet, you will need to procure 100 ROSE from a centralized exchange. &lt;br&gt;
For this tutorial, we are assuming a testnet setup, so you can get your 100 TEST free from the &lt;a href="https://faucet.testnet.oasis.io/?paratime=sapphire" rel="noopener noreferrer"&gt;official faucet&lt;/a&gt;. &lt;br&gt;
It is also advisable that you &lt;a href="https://docs.oasis.io/build/tools/cli/wallet" rel="noopener noreferrer"&gt;create or import a &lt;strong&gt;secp256k1-bip44&lt;/strong&gt; account&lt;/a&gt; to use with the Ethereum-compatible tooling like Hardhat.&lt;/p&gt;

&lt;p&gt;The next step is to select the network - &lt;strong&gt;mainnet&lt;/strong&gt; or &lt;strong&gt;testnet&lt;/strong&gt;, and also the initial administrator account of the app, say &lt;strong&gt;myaccount&lt;/strong&gt;. The CLI will automatically update the manifest file with the assigned app identifier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl create --network testnet --account myaccount
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once done, the CLI will also output the new identifier. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Created ROFL application: rofl1qqn9xndja7e2pnxhttktmecvwzz0yqwxsquqyxdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the app deployer account the default initial admin for any update to the app's configuration. You can always change the admin address at any point.&lt;br&gt;
&lt;strong&gt;Note&lt;/strong&gt;: The CLI implements a simple governance mechanism. Here, the app's admin is a single account, and even a smart contract can be the admin. It is also possible to implement advanced agent governance mechanisms like using multi-sigs or DAOs with veto powers to control the upgrade process.&lt;/p&gt;

&lt;p&gt;Now, a final note about the App ID. It is derived using one of the two schemes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creator address + creator account nonce: This is the default. It helps run tests, e.g. in &lt;a href="https://docs.oasis.io/build/tools/localnet" rel="noopener noreferrer"&gt;sapphire-localnet&lt;/a&gt;, where you want a deterministic app ID.&lt;/li&gt;
&lt;li&gt;Creator address + block round number + index of the &lt;strong&gt;rofl.Create&lt;/strong&gt; transaction in the block: This is when you want a non-deterministic approach. It is the preferred mode in production environments. It deters potential attackers from determining the app ID in advance, even if they knew the creator address.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To select which app ID derivation scheme you want, you can simply pass the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/rofl#create" rel="noopener noreferrer"&gt;--scheme parameter&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Build&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This operation brings together &lt;strong&gt;compose.yaml&lt;/strong&gt;, specific operating system components, and the hash of a trusted block on the Sapphire chain. As a result, you can safely execute the app inside a TEE.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff44d8ldmb2a1xkagzg75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff44d8ldmb2a1xkagzg75.png" alt=" " width="432" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whenever any part of the app changes, this step is necessary before deploying. The build process takes the compose file together with other ROFL artifacts and deterministically generates a bundle that you can deploy later.&lt;br&gt;
Another function of the build process is to compute the enclave identity of the bundle. This is needed during remote attestation to authenticate the app instances before they can be allowed to access the key management system and other features.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl build
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this step generates a ROFL bundle to be used later for deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ROFL app built and bundle written to 'myapp.default.orc'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Update On-chain App Config&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Any changes to the &lt;a href="https://docs.oasis.io/build/rofl/features/manifest#policy" rel="noopener noreferrer"&gt;app's policy&lt;/a&gt; defined in the manifest also require updating the on-chain app config, so that the changes can take effect.&lt;br&gt;
The designated admin account can issue an update transaction by running the CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl update
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can automate the build and verify steps using the &lt;a href="https://github.com/oasisprotocol/build-deploy-rofl-action" rel="noopener noreferrer"&gt;build-deploy-rofl-action&lt;/a&gt; GitHub Action. More on this later.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Deploy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is one of the most detailed sections of the workflow. &lt;/p&gt;

&lt;p&gt;A ROFL app can be deployed to Sapphire or Cipher paratimes where the ROFL module has been installed. For our purposes, we will proceed with &lt;a href="https://docs.oasis.io/build/sapphire/network" rel="noopener noreferrer"&gt;Sapphire&lt;/a&gt;, as it implements all ROFL functionalities.&lt;/p&gt;

&lt;p&gt;You can deploy your app in several ways to a &lt;a href="https://docs.oasis.io/node/run-your-node/rofl-node" rel="noopener noreferrer"&gt;ROFL node&lt;/a&gt;, defined as a light Oasis Node with support for TEE and configured Sapphire runtime. I will discuss in detail on using the ROFL marketplace and GitHub Actions options. &lt;/p&gt;

&lt;p&gt;Alternatively, you can copy over the ROFL bundle to your ROFL node manually and configure it. As the ROFL node is a separate and elaborate topic, not in the scope of this tutorial, we will not go into details here, so check out the &lt;a href="https://docs.oasis.io/node/run-your-node/rofl-node#hosting-the-rofl-app-bundle-directly" rel="noopener noreferrer"&gt;quick guide&lt;/a&gt; for hosting the ROFL bundle directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy on ROFL Marketplace&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Oasis CLI has built-in support for renting a machine on the ROFL marketplace and deploying an app. You can get a list of the default Oasis-managed ROFL providers with this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl deploy --show-offers
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Using provider: oasis1qp2ens0hsp7gh23wajxa4hpetkdek3swyyulyrmz (oasis1qp2ens0hsp7gh23wajxa4hpetkdek3swyyulyrmz)

Offers available from the selected provider:
- playground_short [0000000000000001]
  TEE: tdx | Memory: 4096 MiB | vCPUs: 2 | Storage: 19.53 GiB
  Price: 5.0 TEST/hour
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to select a different provider and offer, you can do so by using the &lt;strong&gt;--provider&lt;/strong&gt; and &lt;strong&gt;--offer&lt;/strong&gt; &lt;a href="https://docs.oasis.io/build/tools/cli/rofl#deploy" rel="noopener noreferrer"&gt;parameters&lt;/a&gt;, respectively.&lt;/p&gt;

&lt;p&gt;For this tutorial, let us proceed with the default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl deploy
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Using provider: oasis1qp2ens0hsp7gh23wajxa4hpetkdek3swyyulyrmz (oasis1qp2ens0hsp7gh23wajxa4hpetkdek3swyyulyrmz)
Pushing ROFL app to OCI repository 'rofl.sh/0ba0712d-114c-4e39-ac8e-b28edffcada8:1747909776'...
No pre-existing machine configured, creating a new one...
Taking offer: playground_short [0000000000000001]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this command is threefold.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It copies over the ROFL bundle .orc to an Oasis-managed OCI repository &lt;strong&gt;rofl.sh&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;It pays offer &lt;strong&gt;playground_short&lt;/strong&gt; with ID &lt;strong&gt;0000000000000001&lt;/strong&gt; to provider &lt;strong&gt;oasis1qp2ens0hsp7gh23wajxa4hpetkdek3swyyulyrmz&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;It returns the machine ID and stores it in the manifest file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can check the status of your active ROFL machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl machine show
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;Provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;oasis1qp2ens0hsp7gh23wajxa4hpetkdek3swyyulyrmz&lt;/span&gt;
&lt;span class="na"&gt;ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;00000000000000a2&lt;/span&gt;
&lt;span class="na"&gt;Offer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;      &lt;span class="m"&gt;0000000000000001&lt;/span&gt;
&lt;span class="na"&gt;Status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;accepted&lt;/span&gt;
&lt;span class="na"&gt;Creator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;oasis1qpupfu7e2n6pkezeaw0yhj8mcem8anj64ytrayne&lt;/span&gt;
&lt;span class="na"&gt;Admin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;oasis1qpupfu7e2n6pkezeaw0yhj8mcem8anj64ytrayne&lt;/span&gt;
&lt;span class="na"&gt;Node ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;bOlqho9R3JHP64kJk+SfMxZt5fNkYWf6gdhErWlY60E=&lt;/span&gt;
&lt;span class="na"&gt;Created at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2025-05-22 15:01:47 +0000 UTC&lt;/span&gt;
&lt;span class="na"&gt;Updated at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2025-05-22 15:01:59 +0000 UTC&lt;/span&gt;
&lt;span class="na"&gt;Paid until&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2025-05-22 16:01:47 +0000 UTC&lt;/span&gt;
&lt;span class="na"&gt;Proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;m162.test-proxy-a.rofl.app&lt;/span&gt;
  &lt;span class="na"&gt;Ports from compose file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;5678 (frontend)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://p5678.m162.test-proxy-a.rofl.app&lt;/span&gt;
&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;TEE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;Intel TDX&lt;/span&gt;
  &lt;span class="na"&gt;Memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;4096 MiB&lt;/span&gt;
  &lt;span class="na"&gt;vCPUs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;Storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;20000 MiB&lt;/span&gt;
&lt;span class="na"&gt;Deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;App ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rofl1qpjsc3qplf2szw7w3rpzrpq5rqvzv4q5x5j23msu&lt;/span&gt;
  &lt;span class="na"&gt;Metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;net.oasis.deployment.orc.ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rofl.sh/0ba0712d-114c-4e39-ac8e-b28edffcada8:1747909776@sha256:77ff0dc76adf957a4a089cf7cb584aa7788fef027c7180ceb73a662ede87a217&lt;/span&gt;
&lt;span class="na"&gt;Commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;no queued commands&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The details of the machine will show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Machine status and expiration date&lt;/li&gt;
&lt;li&gt;Provider information&lt;/li&gt;
&lt;li&gt;Proxy URLs for any published ports&lt;/li&gt;
&lt;li&gt;Resource allocation (TEE type, memory, CPUs, storage)&lt;/li&gt;
&lt;li&gt;Deployment details&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To view the logs of the app, you need to use this command and sign the request with the app's admin account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl machine logs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although only the app admin can access the logs, the data here is stored unencrypted on the ROFL node. So, during the production stage, you should never print any confidential data to the standard or error outputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Actions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We briefly touched on this during the build process. This is applicable for ROFL apps from CI/CD pipelines. Recap of the &lt;a href="https://github.com/oasisprotocol/build-deploy-rofl-action" rel="noopener noreferrer"&gt;build-deploy-rofl-action&lt;/a&gt; automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can identify configuration errors on every push and pull request with this command, and you don't need to run a full build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oasisprotocol/build-deploy-rofl-action@master&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;testnet&lt;/span&gt;
    &lt;span class="na"&gt;only_validate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Build and Verify&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can verify that your build is reproducible and that enclave IDs match the on-chain state. Any mismatch will fail the build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oasisprotocol/build-deploy-rofl-action@master&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mainnet&lt;/span&gt;
    &lt;span class="na"&gt;skip_update&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;skip_deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Full Deployment&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oasisprotocol/build-deploy-rofl-action@master&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mainnet&lt;/span&gt;
    &lt;span class="na"&gt;wallet_account&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deployer&lt;/span&gt;
    &lt;span class="na"&gt;wallet_import&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;wallet_secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.WALLET_SECRET }}&lt;/span&gt;
    &lt;span class="na"&gt;wallet_algorithm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secp256k1-raw&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, it is time to check that the app is running. It does not matter which deployment path you take; the command is the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl show
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;App&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ID:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;rofl&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;qqn&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="err"&gt;xndja&lt;/span&gt;&lt;span class="mi"&gt;7e2&lt;/span&gt;&lt;span class="err"&gt;pnxhttktmecvwzz&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;yqwxsquqyxdf&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Admin:&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="err"&gt;oasis&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;qrydpazemvuwtnp&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;efm&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="err"&gt;vmfvg&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;tde&lt;/span&gt;&lt;span class="mi"&gt;044&lt;/span&gt;&lt;span class="err"&gt;qg&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;cxwzx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Staked&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;amount:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10000.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Policy:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"quotes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pcs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"tcb_validity_period"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"min_tcb_evaluation_data_number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"tdx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"enclaves"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"z+StFagJfBOdGlUGDMH7RlcNUm1uqYDUZDG+g3z2ik8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"6KfY4DqD1Vi+H7aUn5FwwLobEzERHoOit7xsrPNz3eUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"endorsements"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"any"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fees"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max_expiration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Instances&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;===&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;RAK:&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;AQhV&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;X&lt;/span&gt;&lt;span class="mi"&gt;660&lt;/span&gt;&lt;span class="err"&gt;/+bR&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="err"&gt;REaWYkZNR&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;eAysFShylhe+&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="err"&gt;Ph&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="err"&gt;PM=&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;Node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ID:&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;DbeoxcRwDO&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;Wh&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="err"&gt;bwq&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="err"&gt;rAR&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="err"&gt;wzhiB+LeYn+y&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="err"&gt;lFSGAZ&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="err"&gt;I=&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;Expiration:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows that there is a single instance of the app running on the given node. It also displays its public runtime attestation key (RAK) and the epoch at which its registration will expire if not refreshed. So, if you want to continue working with the app, you will need to periodically refresh the registration.&lt;/p&gt;

&lt;p&gt;You can also check out the status of your app on the Oasis Explorer → Sapphire → ROFL.&lt;br&gt;
&lt;a href="https://explorer.oasis.io/mainnet/sapphire/rofl/app" rel="noopener noreferrer"&gt;Mainnet&lt;/a&gt;&lt;br&gt;
&lt;a href="https://explorer.oasis.io/testnet/sapphire/rofl/app" rel="noopener noreferrer"&gt;Testnet&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Test&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While discussing the initialization phase, I outlined &lt;a href="https://docs.oasis.io/build/rofl/workflow/init#rofl-flavors" rel="noopener noreferrer"&gt;several ways&lt;/a&gt; to do so. So, the testing process will vary based on which option you took.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TDX ROFL containers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No appd and Localnet Required&lt;/strong&gt;&lt;br&gt;
If your app doesn't rely on appd, you can export any secrets required by &lt;strong&gt;compose.yaml&lt;/strong&gt; and execute &lt;strong&gt;podman compose up&lt;/strong&gt; with a simple command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;export SECRET=some_secret
podman compose up --build
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Testing with appd and Localnet&lt;/strong&gt;&lt;br&gt;
If your app is connected to a functional appd, you will need to spin up the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/localnet" rel="noopener noreferrer"&gt;sapphire-localnet&lt;/a&gt;&lt;/strong&gt; Docker image and bind-mount the folder that contains your &lt;strong&gt;rofl.yaml&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker run -it -p8544-8549:8544-8549 -v .:/rofls ghcr.io/oasisprotocol/sapphire-localnet
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will run for a few moments and give an output like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* TDX ROFL detected. Localnet appd service will be accessible via UNIX socket and TCP port
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;UNIX socket (Linux)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Shell

curl --unix-socket ./rofl-appd.sock http://localhost/rofl/v1/app/id
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;TCP port (macOS, Linux)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Shell

curl http://localhost:8549/rofl/v1/app/id
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.oasis.io/build/rofl/features/appd#rofl-clients" rel="noopener noreferrer"&gt;ROFL clients&lt;/a&gt; can connect to the TCP port using one of three ways.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Python&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;oasis_rofl_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RoflClient&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RoflClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8549&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;TypeScript&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RoflClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@oasisprotocol/rofl-client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RoflClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:8549&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;Rust&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;oasis_rofl_client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RoflClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;RoflClient&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:8549"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once all this is done, you can now spin up your services and run tests. Usually we use the same &lt;strong&gt;compose.yaml&lt;/strong&gt; for production and testing. So, the following command is useful to point a service to an alternate Localnet's &lt;strong&gt;rofl-appd.sock&lt;/strong&gt; location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;compose.yaml&lt;/span&gt;

    &lt;span class="s"&gt;volumes&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;${ROFL_APPD_SOCKET:-/run/rofl-appd.sock}:/run/rofl-appd.sock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when you execute &lt;strong&gt;podman compose&lt;/strong&gt;, it brings up your services in the Localnet environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;export SECRET=some_secret
export ROFL_APPD_SOCKET=./rofl-appd.sock
podman compose up --build
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the final step, you are now ready to try out the app or execute your end-to-end integration tests as you see fit. Another option would be to use &lt;strong&gt;sapphire-localnet&lt;/strong&gt; in the form of a GitHub action inside your &lt;a href="https://docs.oasis.io/build/tools/localnet#github-actions" rel="noopener noreferrer"&gt;CI service&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TDX ROFL raw&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Local testing for this is currently not supported. So, if you have initialized with this option, you will need to deploy them on Sapphire Testnet and try them out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SGX ROFL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To test this, the first step is to compile your SGX ROFL with &lt;strong&gt;debug&lt;/strong&gt; option enabled. Invoke this command to create a separate &lt;strong&gt;localnet&lt;/strong&gt; deployment in your ROFL manifest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;rofl.yaml&lt;/span&gt;

&lt;span class="na"&gt;deployments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;localnet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rofl1qqn9xndja7e2pnxhttktmecvwzz0yqwxsquqyxdf&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;testnet&lt;/span&gt;
    &lt;span class="na"&gt;paratime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sapphire&lt;/span&gt;
    &lt;span class="na"&gt;admin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test:bob&lt;/span&gt;
    &lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;oasis rofl build --deployment localnet --offline
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this command produces a bundle named &lt;strong&gt;your-app-name.localnet.orc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now, when you execute the &lt;strong&gt;sapphire-localnet&lt;/strong&gt; Docker image and bind-mount the folder that contains the ROFL manifest, the image will automatically register the ROFL on Localnet and execute it inside the Localnet ROFL node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker run -it -p8544-8548:8544-8548 -v .:/rofls ghcr.io/oasisprotocol/sapphire-localnet
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify that the Localnet .orc bundle was loaded and you can test, look out for this output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; * Detected SGX ROFL bundle: /rofls/rofl-appd-localnet.localnet.orc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This concludes the detailed workflow of how to ROFLize an app. However, other aspects of this process also deserve a tutorial. For example, you may wonder what features a ROFL app has or how to troubleshoot, should you need to. I will write up a bonus guide for these topics next time.&lt;/p&gt;

&lt;p&gt;For a quick chat with the Oasis engineering team for help with specific issues, you can drop your comments in the &lt;strong&gt;dev-central channel&lt;/strong&gt; in the official &lt;a href="https://discord.com/invite/BQCxwhT5wS" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>blockchain</category>
      <category>tee</category>
      <category>devex</category>
    </item>
    <item>
      <title>Better AI Context Management With Privacy. Case Studies: Plurality, Ekai.</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Wed, 24 Jun 2026 07:15:54 +0000</pubDate>
      <link>https://dev.to/dc600/better-ai-context-management-with-privacy-case-studies-plurality-ekai-53jg</link>
      <guid>https://dev.to/dc600/better-ai-context-management-with-privacy-case-studies-plurality-ekai-53jg</guid>
      <description>&lt;p&gt;Earlier this year, I had &lt;a href="https://dev.to/dc600/ai-has-a-memory-problem-decentralization-and-privacy-might-have-a-solution-part-3-2288"&gt;discussed&lt;/a&gt; at length about AI memory challenges and potential solutions. I mentioned a couple of names there who had been working on AI context management, as I firmly believe that is how we solve the memory constraints. &lt;/p&gt;

&lt;p&gt;Here, I will further explore two projects that have progressed in this aspect and offer a glimpse of the AI future that could take our experiences to the next level.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Plurality &amp;amp; portable AI context&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Consider this: what if you did not have to start over constantly, or to reiterate and summarize previous conversations whenever you switch models or start a new session? &lt;/p&gt;

&lt;p&gt;Plurality started by trying to answer this. Their aim: to develop an Open Context Layer. As a result, you could autonomously store your data and chats in specific memory buckets. This would not only help with better context management, but also enable sharing the context as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Context Flow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Billed as a fix for the problem of portable AI memory, Plurality built &lt;strong&gt;&lt;a href="https://plurality.network/ai-context-flow/" rel="noopener noreferrer"&gt;AI Context Flow&lt;/a&gt;&lt;/strong&gt;. The tool works with ChatGPT, Claude, Gemini, Grok, and Perplexity. &lt;/p&gt;

&lt;p&gt;One of the USPs of AI Context Flow is the ingrained privacy control. It thus differs from most other solutions, where cloud storage and data mining are part of the deal, mostly without the knowledge or consent of the users. Plurality teamed up with Oasis for a TEE-based, privacy-first context management, where you can decide what AI can see, you can revoke access at your discretion, and have complete data ownership.&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8ooabpuz3rwruk08h2n0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8ooabpuz3rwruk08h2n0.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's now see how Plurality and Oasis address the privacy question. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI Context Flow solves one problem but opens up a new challenge - the infrastructure issue. Helping portable context flow through other servers is tricky and poses inherent trust gaps.&lt;/p&gt;

&lt;p&gt;The easiest answer that springs to mind is adopting the Model Context Protocol (MCP). It enables agents to access tools, data, memory, and APIs. The infrastructure is powerful and growing as more and more AI products get built on top of it. But the privacy pain point lingers.&lt;/p&gt;

&lt;p&gt;Most people, when they talk about AI privacy, are thinking about the model. But the underlying infrastructure is where most privacy is exposed. When a tool uses MCP, the MCP operator can see everything running through the server. So, you get the portable context but without privacy guardrails. Plurality faced this issue while building AI Context Flow, where user intent, history, and sensitive information were vulnerable to third-party access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Oasis solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oasis comes into the picture by offering its Runtime Off-chain Logic (&lt;a href="https://docs.oasis.io/build/rofl/" rel="noopener noreferrer"&gt;ROFL&lt;/a&gt;) for confidential computation to fix the infrastructure exposure dilemma.  Now, the context can flow through the MCP server running inside a Trusted Execution Environment (TEE). This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The operator cannot read context in memory&lt;/li&gt;
&lt;li&gt;The host OS cannot tamper with execution&lt;/li&gt;
&lt;li&gt;Code running is provable with remote attestation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, when Plurality runs its MCP server on ROFL, the confidentiality of the infrastructure layer is not rooted in mere trust assumptions but actually verifiable. Context is stored and processed within the secure enclave away from prying eyes, and visible and accessible only to the model as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plurality next&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Privacy-focused context management opens up new opportunities. In the next phase, Plurality is focusing on building a context marketplace on top of this foundation.&lt;/p&gt;

&lt;p&gt;Simply stated, the context marketplace aggregates the information and knowledge that usually stays fragmented and in silos to be available in packages that anyone can opt to inject into any AI tool. Here, too, the privacy constraint is the potential deal-breaker. And Oasis, with its privacy layer, enables sharing and monetization of context without accessibility to the parties facilitating the transaction in the marketplace. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Ekai &amp;amp; AI context layer&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The trade-off of using AI extensively is our dependency on the context that we have built meticulously over time, fine-tuning prompts and accumulating layers of responses. &lt;/p&gt;

&lt;p&gt;Ekai has built a developer-focused solution that can seamlessly and cost-efficiently switch among various AI models via smart model routing without losing precious context. Oasis provides the trustless and verifiable privacy engine that such a context engine needs to function. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffz1nqv9xwusjqhduqdti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffz1nqv9xwusjqhduqdti.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It addresses two major pain points in AI today.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access control&lt;/strong&gt;: Access sharing is a common practice among users. They let friends and colleagues share access to AI models for ease of use. This is most prevalent while collaborating on projects. Divulging your actual credentials is a high-risk proposition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent context&lt;/strong&gt;: Sharing access is easy; sharing context is the real challenge. Say, you are working with an agent for an hour, and it has accumulated patterns, decisions, contents, outputs, and the logic connecting everything. This context lives in plaintext and is shareable. But whenever there is a new session, the context is gone, or it is a nightmare to locate and reference it. Sometimes, even within a single session, the context degrades as the session timing progresses, leading to hallucinations. Summarization works with limitations, as compressed details tend to get lost in the AI's memory architecture.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ekai is trying to solve this by becoming the context engine for AI agents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contexto&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Designed as the context layer for AI agents, &lt;strong&gt;&lt;a href="https://www.getcontexto.com/" rel="noopener noreferrer"&gt;Contexto&lt;/a&gt;&lt;/strong&gt; currently works with OpenAI, Anthropic, Google, xAI, OpenRouter, and Groq, while the gateway runs on ROFL. Since it is built as an OpenClaw plugin, migration is not necessary.&lt;/p&gt;

&lt;p&gt;From an architectural point of view, Contexto works by keeping the main thread clean by storing and indexing older work. So, when the agent calls for it, the tool retrieves the relevant context automatically. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjs3s9rfuc68mdvwzpfgt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjs3s9rfuc68mdvwzpfgt.png" alt=" " width="799" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All tasks and subtasks run in isolation and are handled by scoped sub-agents who will return contextualized outputs and assembled context in short and simple results. However, nothing gets thrown out, and if you need to trace the full details, they are recoverable on demand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Oasis adds&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ekai's Control Plane enables storing encrypted API keys on-chain via Oasis &lt;a href="https://docs.oasis.io/build/sapphire/" rel="noopener noreferrer"&gt;Sapphire&lt;/a&gt;, so that you can delegate access with granular controls such as model restrictions, spending limits, and instant revocation. As decryption takes place only within the secure enclave or the TEE, it allows access sharing without credential sharing.&lt;/p&gt;

&lt;p&gt;Now, context. As our session windows with AI models grow, the more we have to lose if trust fails, since the context plaintext is recorded for anyone with access to see or manipulate. This context confidentiality issue is solved with ROFL running the context layer inside a TEE. Result: context is stored, indexed, and retrieved within the secure enclave without ever exposing the plaintext.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ekai next&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As of now, both the Control Plane and the context layer as an OpenClaw plugin are live on mainnet. The next phase involves making persistent context private by default as they design the bringing of the context store into the ROFL enclave. &lt;/p&gt;

&lt;p&gt;This would set the stage for agent-to-agent context routing. When this becomes possible, your agent will be able to collaborate with agents belonging to anyone. These disparate agents can then share relevant context with baked-in rules and privacy policies.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Final words&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I am reminded of Oasis AI head, Marko Stokić's discussion about AI memory in his &lt;a href="https://www.forbes.com/sites/digital-assets/2025/12/12/why-crypto-needs-portable-ai-memory/" rel="noopener noreferrer"&gt;Forbes article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We need confidentially computed, and verifiable portable AI context where the user can decide if and when they want to move across AI models, and the interoperable memory layer is subject to the user's data sovereignty and privacy. Both Plurality and Ekai, adopting a privacy-first approach with Oasis's tech stack, demonstrate their commitment to that future.&lt;/p&gt;

&lt;p&gt;What is your take on these projects working to solve AI's persistent memory problem? Let's hit the comments section.&lt;br&gt;
And if you would want to explore more about how Oasis can help you deploy verifiable agents, the journey starts &lt;a href="https://oasis.net/ai-agents" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>context</category>
      <category>web3</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Privana Is Coming. Private DeFi, No Catch.</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Fri, 19 Jun 2026 09:29:25 +0000</pubDate>
      <link>https://dev.to/dc600/privana-is-coming-private-defi-no-catch-4lcd</link>
      <guid>https://dev.to/dc600/privana-is-coming-private-defi-no-catch-4lcd</guid>
      <description>&lt;p&gt;When web3 started its journey, one of the earliest use cases was decentralized finance (DeFi), and it quickly earned popularity among crypto enthusiasts. Over the years, DeFi has evolved in its scope and impact, and is still the best use case of web3 that invites adoption. However, DeFi has not been an unmitigated success and has its own set of challenges that frustrate users and discourage wider adoption.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The dark side of DeFi&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The biggest pain point in DeFi is &lt;a href="https://privana.finance/blog/how-privana-protects-web3-from-mev" rel="noopener noreferrer"&gt;MEV&lt;/a&gt;, or maximal extractable value. For a long time, users had to accept MEV as an invisible tax, although by definition, it is an oversimplification to call it bad. Yet many veteran users cannot escape the clutches of MEV's ugly side, and inexperienced users fall prey to it unwittingly as they navigate the world of DeFi.&lt;/p&gt;

&lt;p&gt;Here are the most prevalent MEV exploits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a sandwich attack, bots profit like this: notice the user awaiting a swap, buy the token, push the price up, then execute the user's trade at a worse price, and immediately sell so that the user gets fewer tokens.&lt;/li&gt;
&lt;li&gt;In frontrunning, when bots notice a pending transaction, they copy and submit the same trade with higher gas fees, thus jumping the queue at the user's disadvantage.&lt;/li&gt;
&lt;li&gt;In back-running, bots execute transactions immediately after a large trade to cash in on the arbitrage opportunity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Researchers have noted how users lose hundreds of millions of their funds due to poor defence against such attacks.&lt;/p&gt;

&lt;p&gt;It is not that solutions don't exist. But protection against MEV is still optional, and if users don't know exactly what to do or how, the bots will collect their dues. Public mempools and lack of privacy are the other side of the coin.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Enter private DeFi&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Oasis, which has been perfecting its privacy-first infrastructure, has joined the fray in offering an alternative to old, flawed DeFi with a new application - &lt;a href="https://oasis.net/blog/privana-liquefaction-implementation" rel="noopener noreferrer"&gt;Privana&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In tech-savvy speak, it combines Sapphire (only production-ready confidential EVM), secure enclaves as in TEEs, encrypted mempools, liquefaction, key encumbrance, and smart privacy to create a consumer-facing, user-friendly private DeFi solution. Let's unpack the user benefits instead of decoding jargon or justifying technical excellence.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Privana&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Simply stated, Privana offers private swaps, automated yields, and zero MEV in multi-chain operations (Ethereum, Base, HyperEVM).&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fju9z6kj1x2mf1q834qec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fju9z6kj1x2mf1q834qec.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;USPs&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Privacy-first&lt;/strong&gt; - All user transactions are TEE-protected, and as they never hit the public mempools, bots can neither see nor target the trades. Result: protection from the adversarial effects that MEV inevitably causes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automation&lt;/strong&gt; - Users can set the operational rules and let everything execute in auto-mode. Their keys remain private, so no sharing, no exposure, no exploit risks - all in 3 steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deposit into the vault - Users send their tokens to the Privana vault, a secure enclave.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set preferences - Users choose their swap conditions, yield settings, and app permissions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Activate strategy - Once users approve, they can sit back and forget about manual intervention. Swaps, yield allocation, and rebalancing all run in the background without exposing any of the activity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-custody&lt;/strong&gt; - Applying the concept of key encumbrance, self-custody design is achieved through non-extractable keys, so no one can access or move the key outside the policy set by the users, not even by Privana developers in the backend. This also redefines self-custody as it empowers users to govern the keys instead of holding them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-chain&lt;/strong&gt; - Users don't need the expertise or headache of hopping between chains as one interface, no bridges, no wallet-switching leads to a seamless experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A quick overview of Privana's capabilities and what other major protocols offer, showcasing its versatile advantages with structural privacy design.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpfoj1ydf0lil2usefjsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpfoj1ydf0lil2usefjsc.png" alt=" " width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Privana&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Privana does not claim to be the only solution in the DeFi space. So, when we do a deep dive into &lt;a href="https://privana.finance/blog/2026-comparing-defi-privacy-solutions" rel="noopener noreferrer"&gt;comparing&lt;/a&gt; what is available right now, it clearly indicates that no one else combines everything. It is particularly interesting to see the trade-offs, even when tools have baked-in privacy.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fobsvhd8ch1qkdjd81ih5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fobsvhd8ch1qkdjd81ih5.png" alt=" " width="799" height="420"&gt;&lt;/a&gt;&lt;br&gt;
Privana checks all the boxes.&lt;/p&gt;

&lt;p&gt;No decentralized exchange (DEX) so far has been immune to MEV attacks, and Privana aims to counter this with the idea of encrypted mempools. When transactions are on-chain and public, they sit exposed in the mempool, and any malicious bot on the network can take advantage and undercut even a simple swap. Private RPCs and relays do work with limitations. They successfully hide transactions from the network, but reveal full swap intent to the relay operators.&lt;/p&gt;

&lt;p&gt;A centralized exchange (CEX) solves this particular trust gap of the DEX with internal books, but as the users' keys are in their custody, it opens a new can of worms. In truth, both DEXes and CEXes offer partial solutions with trade-offs. If there is some degree of MEV protection, then on-chain full transparency becomes an issue. If private swaps are possible, they don't come with automation and self-custody. Users usually get either cross-chain swaps or privacy-focused swaps, but not both.&lt;/p&gt;

&lt;p&gt;As a trading interface, Privana does the serious legwork with its privacy-first approach - designed specifically to be private by default and automated without giving up control. This is a long-awaited solution that promises to plug the holes while delivering the optimal DeFi experience for users.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Privana is coming&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Privana roadmap comprehensively lists what users can expect from the product in the coming days.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwl5gme714gd77j2hyxr3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwl5gme714gd77j2hyxr3.png" alt=" " width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The impending launch of Privana is also in sync with the &lt;a href="https://oasis.net/blog/oasis-new-chapter" rel="noopener noreferrer"&gt;new strategic direction&lt;/a&gt; adopted by Oasis. The protocol already has the underlying infrastructure for implementation. So, instead of solely relying on ecosystem partners to build the dApps, it is now focusing on shipping products that directly bring the benefits of the tech stack to the users.&lt;/p&gt;

&lt;p&gt;Privana promises to be the vanguard. For users, this is a new opportunity as well to transform their DeFi experience for the better.&lt;/p&gt;

&lt;p&gt;There are already several incentives announced for early joiners of &lt;a href="https://privana.finance/" rel="noopener noreferrer"&gt;Privana&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero fees for 90 days&lt;/li&gt;
&lt;li&gt;Founding Member status&lt;/li&gt;
&lt;li&gt;Priority queue at launch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not miss out.&lt;/p&gt;

&lt;p&gt;Let's discuss in the comments your take on Privana and private DeFi, and what aspects you like the best, and what else you want to be incorporated down the line.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>decentralizedfinance</category>
      <category>privacy</category>
      <category>uxdesign</category>
    </item>
    <item>
      <title>ROFLize an App? Part 1: ROFL Workflow To Initialization</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Thu, 18 Jun 2026 08:16:32 +0000</pubDate>
      <link>https://dev.to/dc600/roflize-an-app-part-1-rofl-workflow-to-initialization-4m78</link>
      <guid>https://dev.to/dc600/roflize-an-app-part-1-rofl-workflow-to-initialization-4m78</guid>
      <description>&lt;p&gt;Recently, I shared a quickstart guide titled "&lt;a href="https://dev.to/dc600/how-to-enhance-your-app-with-oasis-rofl-a-quickstart-tutorial-3n55"&gt;How To Enhance Your App With Oasis ROFL&lt;/a&gt;". While the tutorial was complete in itself, I skipped some of the finer implementation details to keep it streamlined. Here, in this new 2-part series, I will unpack those sections step by step.&lt;/p&gt;

&lt;p&gt;Rather than covering old ground from the post, which already features a short explainer video and visuals of the architectural breakdown and the workflow overview of the ROFL (runtime off-chain logic) framework, let's dive straight into the developers' POV here.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Workflow&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6sp44ft4kur866hrve63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6sp44ft4kur866hrve63.png" alt=" " width="799" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As this visual shows, there is a dedicated Trusted Execution Environment (TEE) for every app that runs inside ROFL. An Oasis node provides the TEE from its ORC bundle, consisting of a zip archive containing the program binaries and metadata required for execution. &lt;br&gt;
As a result, the ROFL apps registering on Oasis's network can easily authenticate to on-chain smart contracts and also transparently gain access to the decentralized per-app key management system.&lt;/p&gt;

&lt;p&gt;The TEE ensures app security and enables secure communication with the outside world. The function of the light client here is to establish a fresh view of the Oasis consensus layer. This not only provides a source of approximate time references but also acts as an integrity gatekeeper for the verification of all on-chain states.&lt;br&gt;
In addition, the app also generates a set of ephemeral cryptographic keys, used in remote attestation and on-chain registration, and then discarded at the end of the session to provide forward and backward secrecy. &lt;br&gt;
The authentication process for on-chain modules is completed by signing and submitting special transactions. As a result, the app can now perform any arbitrary task and interact with the outside world through network connections, authenticated via HTTPS/TLS, or other methods such as light clients for other chains.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We need 2 tools for ROFL development and deployment.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Oasis CLI&lt;/strong&gt;: The Oasis command-line interface (CLI) is an all-in-one tool, handling wallet management, app registration, building, deployment, and replica management. For a detailed overview and installation instructions, check out the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/" rel="noopener noreferrer"&gt;oasis&lt;/a&gt;&lt;/strong&gt; command. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Docker&lt;/strong&gt;: Having a containerized build environment is an essential prerequisite, as it ensures that you do not have to install a handful of Intel-specific libraries and dependencies on your system. Moreover, the &lt;strong&gt;Compose&lt;/strong&gt; function will help test the ROFL locally before you deploy it on-chain.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can choose any of the 3 following ways to continue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preferred&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This method uses Oasis CLI and a container for building and testing. &lt;br&gt;
First, you need to &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/setup/" rel="noopener noreferrer"&gt;download and install&lt;/a&gt;&lt;/strong&gt; the Oasis CLI on your platform.&lt;br&gt;
Next, test the functionality by building the ROFL app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;oasis rofl build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conservative&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this method, there are containers everywhere. &lt;br&gt;
If there are any issues while installing the Oasis CLI locally, or perhaps you want to skip the Oasis CLI step altogether, the workaround is to run the &lt;strong&gt;oasis&lt;/strong&gt; command from the &lt;strong&gt;&lt;a href="https://github.com/oasisprotocol/oasis-sdk/pkgs/container/rofl-dev" rel="noopener noreferrer"&gt;rofl-dev&lt;/a&gt;&lt;/strong&gt; image.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You must be careful when you bind-mount the Oasis CLI config folder, which contains your wallet. Otherwise, there is a risk of losing access to your (funded) accounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Invoke &lt;strong&gt;oasis&lt;/strong&gt; from the &lt;strong&gt;rofl-dev&lt;/strong&gt; image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; .:/src &lt;span class="nt"&gt;-v&lt;/span&gt; ~/.config/oasis:/root/.config/oasis &lt;span class="nt"&gt;-it&lt;/span&gt; ghcr.io/oasisprotocol/rofl-dev:main oasis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For MacOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; .:/src &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"~/Library/Application Support/oasis/"&lt;/span&gt;:/root/.config/oasis &lt;span class="nt"&gt;-it&lt;/span&gt; ghcr.io/oasisprotocol/rofl-dev:main oasis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Windows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="nb"&gt;run&lt;/span&gt; &lt;span class="na"&gt;--platform &lt;/span&gt;&lt;span class="kd"&gt;linux&lt;/span&gt;&lt;span class="na"&gt;/amd&lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt; &lt;span class="na"&gt;--rm -v &lt;/span&gt;.:/src &lt;span class="na"&gt;-v &lt;/span&gt;&lt;span class="nv"&gt;%USERPROFILE%&lt;/span&gt;&lt;span class="na"&gt;/AppData/Local/oasis&lt;/span&gt;/:/root/.config/oasis &lt;span class="na"&gt;-it &lt;/span&gt;&lt;span class="kd"&gt;ghcr&lt;/span&gt;.io/oasisprotocol/rofl&lt;span class="na"&gt;-dev&lt;/span&gt;&lt;span class="nl"&gt;:main&lt;/span&gt; &lt;span class="kd"&gt;oasis&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This step here is optional. You can choose to add &lt;strong&gt;oasis&lt;/strong&gt;alias to your shell start-up script. This will mimic as if Oasis CLI was installed locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Linux:&lt;br&gt;
~/.bashrc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;oasis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'docker run --platform linux/amd64 --rm -v .:/src -v ~/.config/oasis:/root/.config/oasis -it ghcr.io/oasisprotocol/rofl-dev:main oasis'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For MacOS:&lt;br&gt;
~/.bash_profile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;oasis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'docker run --platform linux/amd64 --rm -v .:/src -v "~/Library/Application Support/oasis/":/root/.config/oasis -it ghcr.io/oasisprotocol/rofl-dev:main oasis'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advanced&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This method uses native Oasis CLI and ROFL build utils. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: It is for &lt;strong&gt;linux/amd64&lt;/strong&gt; only.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first step is installing the Oasis CLI locally.&lt;br&gt;
Next, you need to install tools for creating and encrypting partitions and Quick Emulator (QEMU). For a Debian-based Linux, this can be done by running this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;squashfs-tools cryptsetup-bin qemu-utils
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you may be looking to build SGX and TDX-raw ROFL bundles. In that case, it will require the installation of the Rust toolchain and Fortanix libraries. It is a separate detailed process involving &lt;strong&gt;Oasis Core prerequisites&lt;/strong&gt;, which I will elaborate on in a later post. For now, you just follow the steps outlined &lt;a href="https://docs.oasis.io/core/development-setup/prerequisites" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You do not need a working SGX/TDX TEE when building ROFL natively. Even an Intel-based CPU and the corresponding libraries will suffice.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Containerize&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We have often mentioned that an ROFL app needs to be containerized. What does this mean? A container is basically a controlled environment that includes the exact version of the operating system, both system and user libraries, as well as your configured service. The image of the container is uploaded to an OCI file server, such as &lt;strong&gt;&lt;a href="https://docker.io/" rel="noopener noreferrer"&gt;docker.io&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry" rel="noopener noreferrer"&gt;ghcr.io&lt;/a&gt;&lt;/strong&gt;. The server hosting your app can then download it, consisting two files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-bot
├── bot.py           # A python bot script
└── requirements.txt # Python dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will use &lt;strong&gt;&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/strong&gt; to containerize. However, you can choose to go with &lt;strong&gt;&lt;a href="https://www.podman.io/" rel="noopener noreferrer"&gt;Podman&lt;/a&gt;&lt;/strong&gt; instead of Docker, as once the app is deployed to a ROFL node, the containers there will be orchestrated by Podman anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here we will create a file called &lt;strong&gt;Dockerfile&lt;/strong&gt; inside the project folder. This will tell Docker to compile a &lt;strong&gt;python-based image&lt;/strong&gt; and add the &lt;strong&gt;python bot script&lt;/strong&gt; on top of it.&lt;/p&gt;

&lt;p&gt;Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:alpine3.17&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /bot&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./bot.py ./requirements.txt /bot&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["python", "bot.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Compose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The function of &lt;strong&gt;&lt;a href="https://docs.docker.com/reference/compose-file/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;&lt;/strong&gt; is to orchestrate the containers you will be using. This ensures correct sequencing, defining storage points, networking, and other functionalities. You can create &lt;strong&gt;compose.yaml&lt;/strong&gt; with the following command.&lt;/p&gt;

&lt;p&gt;compose.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;python-bot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docker.io/YOUR_USERNAME/YOUR_PROJECT"&lt;/span&gt;
    &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;TOKEN=${TOKEN}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may need to adjust the &lt;strong&gt;image:&lt;/strong&gt; field(s) to fit your needs. The &lt;strong&gt;image:&lt;/strong&gt; field must always point to a &lt;strong&gt;publicly accessible OCI registry&lt;/strong&gt; from where your image will be downloaded for execution. &lt;br&gt;
If you are replacing the &lt;strong&gt;image:&lt;/strong&gt; field with a fully qualified domain of the OCI server you use, followed by your username, the field will look like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;docker.io/your_username/my-bot&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ghcr.io/your_username/my-bot&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Always specify the container image URL with a fully qualified domain name, e.g., &lt;strong&gt;docker.io/ollama/ollama&lt;/strong&gt; and not just &lt;strong&gt;ollama/ollama&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Build and Push&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, you can build the container image and tag it using &lt;strong&gt;docker compose&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check the compose setup locally, test it with this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To stop once done, use this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you have completed building and tagging the images, the next step is to push the container images to a publicly accessible OCI registry that we referred to earlier (&lt;strong&gt;&lt;a href="https://docker.io/" rel="noopener noreferrer"&gt;docker.io&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry" rel="noopener noreferrer"&gt;ghcr.io&lt;/a&gt;&lt;/strong&gt;).&lt;br&gt;
For first-time use, you need to perform an authentication step by running this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once done and for all those already logged in before, this command will upload the container images to the registry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For first-timers, when pushing the image to GitHub containers, please ensure &lt;a href="https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#configuring-visibility-of-packages-for-your-personal-account" rel="noopener noreferrer"&gt;public package visibility&lt;/a&gt; is properly configured.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Pin Your Image Hash&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the final step in the containerizing process. It helps prevent another container image from being pulled inside ROFL. You do it by pinning the image digest inside &lt;strong&gt;compose.yaml&lt;/strong&gt;. To fetch the &lt;strong&gt;sha256:...&lt;/strong&gt; digest, try invoking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images &lt;span class="nt"&gt;--digests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you need to append &lt;strong&gt;@&lt;/strong&gt; and the digest next to the image tag in your &lt;strong&gt;compose.yaml&lt;/strong&gt;. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docker.io/MY_USERNAME/my-bot@sha256:9633593eb9e8395023cb0d926982602978466ec003efa189d94a34e7bea6ec0d"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Init&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the final section of this tutorial, we will see how to initialize the ROFL app. Before starting, you need to choose from the 3 options below. Notably, whatever you choose, it would likely be a trade-off between the Trusted Computing Base (TCB) size and ease of use.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TDX containers ROFL (default)&lt;/strong&gt;: A Docker compose-based container service packed in a secure virtual machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Raw TDX ROFL&lt;/strong&gt;: A Rust app compiled as the init process of the operating system and packed in a secure virtual machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SGX ROFL&lt;/strong&gt;: A Rust app with fixed memory allocation compiled and packed into a single secure binary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Init App Directory and Manifest&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first step is to create the basic directory structure for the app using the Oasis CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl init my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now have a &lt;strong&gt;my-app&lt;/strong&gt; directory and have also initialized a ROFL manifest file. As noted above, the default is a TDX container-based ROFL. To select one of the other options, you need to use the &lt;strong&gt;--kind&lt;/strong&gt; parameter.&lt;/p&gt;

&lt;p&gt;As a result of the &lt;strong&gt;init&lt;/strong&gt; command, you will get the following output summary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Creating a new ROFL app with default policy...
Name:     my-app
Version:  0.1.0
TEE:      tdx
Kind:     container
Git repository initialized.
Created manifest in 'rofl.yaml'.
Run `oasis rofl create` to register your ROFL app and configure an app ID.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The directory structure (omitting git artifacts) will look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myapp
├── compose.yaml        # Container compose file.
└── rofl.yaml           # ROFL app manifest.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The &lt;a href="https://docs.oasis.io/build/rofl/features/manifest" rel="noopener noreferrer"&gt;manifest&lt;/a&gt; that this step initialized is a ROFL feature that contains metadata, secrets, and requested resources. These can be modified either manually or by using the CLI commands and require to be discussed in detail separately. For now, we have finished initialization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/dc600/roflize-an-app-part-2-create-build-deploy-test-2hmk"&gt;concluding part&lt;/a&gt; of the series, I will guide you through the next steps in ROFLizing your app, involving create, build, deploy, and test processes. &lt;br&gt;
Until then, if you encounter any issues, you can have a quick chat with the Oasis engineering team for help by dropping your comments in the &lt;strong&gt;dev-central channel&lt;/strong&gt; in the official &lt;a href="https://discord.com/invite/BQCxwhT5wS" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>blockchain</category>
      <category>tee</category>
      <category>devex</category>
    </item>
    <item>
      <title>Guide To Deploying A Trustless Eliza Agent With Oasis ROFL</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Thu, 28 May 2026 06:53:48 +0000</pubDate>
      <link>https://dev.to/dc600/guide-to-deploying-a-trustless-eliza-agent-with-oasis-rofl-48hh</link>
      <guid>https://dev.to/dc600/guide-to-deploying-a-trustless-eliza-agent-with-oasis-rofl-48hh</guid>
      <description>&lt;p&gt;Oasis introduced the framework for runtime off-chain logic (ROFL) to help build and run apps off-chain while ensuring privacy and maintaining trust with on-chain verifiability. For most people, this &lt;a href="https://www.youtube.com/watch?v=JFYnEyMFgRE" rel="noopener noreferrer"&gt;explainer video&lt;/a&gt; would be enough. But for developers and dApp builders, who want to try things out themselves, a deeper dive is worth it.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will demonstrate how to build and deploy a trustless Eliza agent with Oasis ROFL.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Objective&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The objective is to have a working Eliza agent running inside a ROFL Trusted Execution Environment (TEE). I will also show how to get it registered and validated as a trustless agent in the &lt;a href="https://eips.ethereum.org/EIPS/eip-8004" rel="noopener noreferrer"&gt;ERC-8004&lt;/a&gt; registry. The agent's code will be fully auditable, and anyone can verify the authenticity of the origin of the deployed instance, which is immutable and tamper-proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Refer to the prerequisite section in the &lt;a href="https://dev.to/dc600/how-to-enhance-your-app-with-oasis-rofl-a-quickstart-tutorial-3n55"&gt;ROFL quickstart tutorial&lt;/a&gt; for setup details.&lt;br&gt;
So, right now, we need these to get started.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; (or Podman) with credentials. It can be on docker.io, ghcr.io, or any other public OCI registry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Oasis CLI&lt;/strong&gt; and at least &lt;strong&gt;120 TEST&lt;/strong&gt; tokens in your wallet. Since we are building in the testnet environment, you can get these tokens for free from the &lt;a href="https://faucet.testnet.oasis.io/" rel="noopener noreferrer"&gt;official faucet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js 22+&lt;/strong&gt;. It is for Eliza and helper scripts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenAI API key&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RPC URL&lt;/strong&gt;. It is to access the ERC-8004 registry (e.g. Infura).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pinata JWT&lt;/strong&gt;. It is to store agent information in IPFS.&lt;/li&gt;
&lt;li&gt;At least &lt;strong&gt;2 GiB of memory&lt;/strong&gt; and &lt;strong&gt;10 GB of storage&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Eliza Agent Creation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The first step is to initialize a project using the ElizaOS CLI. Next, prepare it for ROFL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install bun and ElizaOS CLI&lt;/span&gt;
bun &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://bun.sh/install | bash
bun &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @elizaos/cli

&lt;span class="c"&gt;# Create and configure the agent&lt;/span&gt;
elizaos create &lt;span class="nt"&gt;-t&lt;/span&gt; project rofl-eliza
&lt;span class="c"&gt;# 1) Select Pqlite database&lt;/span&gt;
&lt;span class="c"&gt;# 2) Select the OpenAI model and enter your OpenAI key&lt;/span&gt;

&lt;span class="c"&gt;# Test the agent locally&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;rofl-eliza
elizaos start
&lt;span class="c"&gt;# Visiting http://localhost:3000 with your browser should open Eliza UI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Containerize&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this step, you will need to containerize both the app and the ERC-8004 wrapper. &lt;br&gt;
You will notice that the Eliza agent startup wizard has already generated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dockerfile&lt;/strong&gt; - this packs your agent into a container. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docker-compose.yaml&lt;/strong&gt; - this automatically configures, connects, and manages the interdependent &lt;strong&gt;postgres&lt;/strong&gt; and &lt;strong&gt;elizaos&lt;/strong&gt; containers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next step is to make some changes to &lt;strong&gt;docker-compose.yaml&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the PostgreSQL section, you need to replace relative &lt;strong&gt;image: ankane/pgvector:latest&lt;/strong&gt; with &lt;strong&gt;image: docker.io/ankane/pgvector:latest&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You need to name the &lt;strong&gt;elizaos&lt;/strong&gt; image with a corresponding absolute path, e.g. &lt;strong&gt;image: docker.io/YOUR_USERNAME/elizaos:latest&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You need to register the Eliza agent as a trustless agent in the ERC-8004 registry using the &lt;a href="https://github.com/oasisprotocol/erc-8004" rel="noopener noreferrer"&gt;&lt;strong&gt;rofl-8004&lt;/strong&gt;&lt;/a&gt; snippet. Ensure that the environment variables are mapped as is.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;docker-compose.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;rofl-8004&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/oasisprotocol/rofl-8004@sha256:f57373103814a0ca4c0a03608284451221b026e695b0b8ce9ca3d4153819a349&lt;/span&gt;
    &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;RPC_URL=${RPC_URL}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PINATA_JWT=${PINATA_JWT}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/run/rofl-appd.sock:/run/rofl-appd.sock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The validation flow looks something like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvikw8xthetw9s4i6pfpy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvikw8xthetw9s4i6pfpy.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have edited &lt;strong&gt;docker-compose.yaml&lt;/strong&gt;, it is time to build and push.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose build
docker compose push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are looking for full verifiability, you need to pin the digest by appending &lt;strong&gt;image: ...&lt;a class="mentioned-user" href="https://dev.to/sha256"&gt;@sha256&lt;/a&gt;:...&lt;/strong&gt; to all images in &lt;strong&gt;docker-compose.yaml&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Init &amp;amp; Create&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once all previous steps are complete, you will find that the agent is running in a container within a TEE. In this setup, ROFL handles the startup attestation of the container and the secrets in the form of environment variables. As a result, the TEE is completely transparent to the Eliza agent app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl init
oasis rofl create &lt;span class="nt"&gt;--network&lt;/span&gt; testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check out on-chain activity and app details in the &lt;a href="https://explorer.oasis.io/testnet/sapphire" rel="noopener noreferrer"&gt;Oasis Explorer&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Build ROFL bundle&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is where the memory and storage prerequisites come in handy.&lt;br&gt;
First, you need to update the resources section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;rofl.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2048&lt;/span&gt;
  &lt;span class="na"&gt;cpus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-persistent&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can build the ROFL bundle by invoking this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Secrets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this step, we take care of encryption. It involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;End-to-end encrypting of &lt;strong&gt;OPENAI_API_KEY&lt;/strong&gt; and storing it on-chain. &lt;/li&gt;
&lt;li&gt;Providing the &lt;strong&gt;RPC_URL&lt;/strong&gt; and &lt;strong&gt;PINATA_JWT&lt;/strong&gt; values for ERC-8004 registration.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;your-openai-key-here&amp;gt;"&lt;/span&gt; | oasis rofl secret &lt;span class="nb"&gt;set &lt;/span&gt;OPENAI_API_KEY -
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"https://sepolia.infura.io/v3/&amp;lt;YOUR_KEY&amp;gt;"&lt;/span&gt; | oasis rofl secret &lt;span class="nb"&gt;set &lt;/span&gt;RPC_URL -
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;your-pinata-key-here&amp;gt;"&lt;/span&gt; | oasis rofl secret &lt;span class="nb"&gt;set &lt;/span&gt;PINATA_JWT -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then comes the important step of storing the secrets as well as the previously built enclave identities on-chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Deploy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This completes the building of the Eliza agent. Now, we need to deploy it to an ROFL provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Oasis-maintained provider is selected on Testnet, which rents a node for 1 hour by default. You can extend the rental period for more hours, say for 6 hours, by invoking &lt;strong&gt;oasis rofl machine top-up --term hour --term-count 6&lt;/strong&gt; &lt;a href="https://docs.oasis.io/build/tools/cli/rofl#deploy" rel="noopener noreferrer"&gt;command&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Test&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You have successfully built and deployed your very own Eliza agent. You can test if it is running properly with this CLI check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Show machine details (state, proxy URLs, expiration).&lt;/span&gt;
oasis rofl machine show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A successful agent boot means the &lt;strong&gt;Proxy:&lt;/strong&gt; section will show the URL where the agent is accessible. So, for example if it shows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;m1058.opf-testnet-rofl-25.rofl.app&lt;/span&gt;
  &lt;span class="na"&gt;Ports from compose file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;3000 (elizaos)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://p3000.m1058.opf-testnet-rofl-25.rofl.app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the app would be accessible at &lt;strong&gt;&lt;a href="https://p3000.m1058.opf-testnet-rofl-25.rofl.app" rel="noopener noreferrer"&gt;https://p3000.m1058.opf-testnet-rofl-25.rofl.app&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ERC-8004 Registration and Validation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is not an automatic step and needs to be completed to get this Eliza agent registered and validated as a trustless agent in the ERC-8004 registry. When you are running the agent for the first time, the &lt;strong&gt;rofl-8004&lt;/strong&gt; service will derive the Ethereum address for registering it. To go ahead, you will need to fund that account with some ETH to pay for the gas fees.&lt;/p&gt;

&lt;p&gt;Use this command to fetch your app logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl machine logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;Please top it up&lt;/strong&gt; line will show the derived address. After funding it, your agent is registered and validated, and ready to go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Please note&lt;/strong&gt;: All logs here are accessible to the app admin, as they are stored &lt;strong&gt;unencrypted on the ROFL node&lt;/strong&gt;. So, remember not to put any private information here.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Demo&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This guide shows how you can build your own agent, but if you need to check out a full-fledged demo of how it looks and works, there is an example in the official Oasis repository.&lt;br&gt;
&lt;a href="https://github.com/oasisprotocol/demo-trustless-agent" rel="noopener noreferrer"&gt;&lt;strong&gt;Trustless Agent Demo&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a quick chat with the Oasis engineering team for help with specific issues, you can drop your comments in the &lt;strong&gt;dev-central channel&lt;/strong&gt; in the official &lt;a href="https://discord.com/invite/BQCxwhT5wS" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>trustless</category>
      <category>eliza</category>
      <category>agents</category>
    </item>
    <item>
      <title>Key Encumbrance: The Primitive That Makes Programmable Privacy Possible</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Wed, 27 May 2026 08:34:18 +0000</pubDate>
      <link>https://dev.to/dc600/key-encumbrance-the-primitive-that-makes-programmable-privacy-possible-n04</link>
      <guid>https://dev.to/dc600/key-encumbrance-the-primitive-that-makes-programmable-privacy-possible-n04</guid>
      <description>&lt;p&gt;Over the years, blockchain technology has unlocked key primitives that drive utility and adoption. Multisigs, multi-party computation, ERC-4337 (account abstraction), smart wallets, etc., have all contributed to making it more accessible and user-friendly. &lt;/p&gt;

&lt;p&gt;But problems persist. Public blockchains mean absolute transparency and on-chain visibility, leading to constant exposure and risk of exploitation. Then there is the need to always coordinate among people to enable the "multi" aspect for security. Most of the major chains are also siloed, and interoperability is still very limited in application. Moreover, key custody is binary, making private key management both challenging and often trust-dependent. And this does not inspire user confidence or mass adoption. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Key Encumbrance&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Oasis has been at the forefront of privacy-first blockchain technology and utility, and has actively supported the development of primitives to advance this. &lt;br&gt;
Last year the protocol collaborated with researchers at IC3 and Cornell Tech to explore practical implementations of &lt;a href="https://oasis.net/blog/liquefaction-most-traded-nft-in-history" rel="noopener noreferrer"&gt;Liquefaction&lt;/a&gt; on Sapphire.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key encumbrance&lt;/strong&gt; is a core benefit of Liquefaction that proposes an elegant solution for the pain points discussed earlier. Here, the private key is generated inside a TEE enclave and can only be interacted with through &lt;strong&gt;programmable policies&lt;/strong&gt;. &lt;br&gt;
As a result, the key is completely secure and tamper-proof, with neither the end users nor the delegates nor the operators and developers ever having access to the keys.    &lt;/p&gt;

&lt;p&gt;So, when users try to sign with their keys, that is only possible when the signature request satisfies the policy conditions. Simply stated, the key never leaves the secure enclave, and the policy enforcement is end-to-end encrypted and processed only inside the enclave. Therefore, the assets linked to the key enjoy complete security and privacy, and can be moved, traded, shared, or pooled without on-chain exposure or tracking.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How It Works&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The major question now is whether this is actually implementable. Short answer, yes.&lt;/p&gt;

&lt;p&gt;The USP is adding &lt;strong&gt;programmable policies&lt;/strong&gt; that must be passed before the key inside the TEE encrypts and signs the transaction on the target chain. Interestingly, this does not need a multisig solution, and a single entity can operate under multiple policy scopes.&lt;br&gt;
As a practical application of this concept, Oasis has developed encumbrance-powered vault infrastructure for DeFi, bringing privacy, security, and ease of use together.&lt;/p&gt;

&lt;p&gt;The architecture is simple, with a user interface where the application interacts with the functionality via an SDK. Any request or intent passes into the enclave, consisting of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A policy engine&lt;/li&gt;
&lt;li&gt;The encumbered key&lt;/li&gt;
&lt;li&gt;A transaction executor&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this setup, the request encounters the policy engine that stores the policies in a confidential smart contract. If and when the request satisfies the policy conditions, the key signs and authorizes the request. In case the policy conditions are not met, the request fails, and there is no further action. Simply put, instead of the user accessing and potentially exposing the private key, the key remains inaccessible within the enclave, and only meeting the policy criteria triggers the smart contract to sign the transaction.&lt;/p&gt;

&lt;p&gt;This system becomes particularly powerful when other chains are involved. Even though Oasis has its own network, users do not need to deposit the assets to Oasis, which simplifies interoperability. The assets are stored in a confidential container where the users can generate wallets for target chains and sign with them over programmable policies. So, the user assets stay where they are, while Oasis functions as the ultimate security layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Encumbrance? Why Not Multisig?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Multisigs have been useful for a long time, but come with limitations. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every action lives on-chain&lt;/li&gt;
&lt;li&gt;Users are locked to a single chain&lt;/li&gt;
&lt;li&gt;No action is possible without coordination and a quorum&lt;/li&gt;
&lt;li&gt;Enforcement needs a dedicated contract&lt;/li&gt;
&lt;li&gt;Delegation entails adding/removing signers, which also requires authorized signatures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key encumbrance&lt;/strong&gt; does away with these limitations.&lt;/p&gt;

&lt;p&gt;Adding or revoking access can be done by updating a policy. As the keys are never shared and truly private, the rules are enforced only through the policy engine.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;programmable policies&lt;/strong&gt; are the definitive point of difference, making encumbrance a groundbreaking and powerful primitive for future utility and user convenience. In practice, these policies come with tangible capabilities and benefits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Non-custodial automatic execution&lt;/strong&gt;. If an asset's price threshold is breached, the enclave verifies with the policy condition, and the key signs a trade/sell. Neither manual approval is needed, nor is there a need for a bot with private key access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Composable policy chains&lt;/strong&gt;. Multi-chain functionality is in-built. So, profit from a sale or trading into a stablecoin can be routed to a different chain where it can earn passive yield - the entire process is maintained by using the policy engine without manual intervention or signing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scoped bot access&lt;/strong&gt;. By adding policies to an encumbered key - it can be anything, such as assigning a dollar value threshold, specifying transactional time windows, or assets whitelisted with pre-set criteria, bot usage can be streamlined. Here, the bot will access the signature via an API without ever having key access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Delegation without quorum&lt;/strong&gt;. Policy access can be programmed to have an expiry date of 30 days. With no key sharing, and keys managed and enforced inside TEEs, no human coordination or quorum criteria are needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Session-based gaming&lt;/strong&gt;. Application in gaming and related use cases where policy can pre-determine a threshold and time window, and handle signatures accordingly without needing to leave the game to approve transactions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Final Takeaway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Current user experience in the blockchain and web3 space is riddled with poor key management and compromised access control. Encumbered keys make it possible for the next generation of applications to integrate programmability, privacy, and permissionless utility. &lt;br&gt;
The proof of concept is already under development by Oasis using its own tech stack and primitives - &lt;a href="https://oasis.net/solutions-defi" rel="noopener noreferrer"&gt;private DeFi with Privana&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further reading: Primitives by Oasis&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://oasis.net/blog/storage-encryption-access-management" rel="noopener noreferrer"&gt;Decentralized Storage&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://oasis.net/blog/rofl-proxy-frontend-hosting" rel="noopener noreferrer"&gt;Proxy Support for Frontend Hosting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://oasis.net/blog/multichain-wallet-agents" rel="noopener noreferrer"&gt;Multi-chain Wallet&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://oasis.net/blog/decentralized-key-management-agents" rel="noopener noreferrer"&gt;Decentralized Key Management&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blockchain</category>
      <category>web3</category>
      <category>privacy</category>
      <category>keymanagement</category>
    </item>
    <item>
      <title>How To Enhance Your App With Oasis ROFL: A QuickStart Tutorial</title>
      <dc:creator>DC</dc:creator>
      <pubDate>Wed, 22 Apr 2026 14:34:03 +0000</pubDate>
      <link>https://dev.to/dc600/how-to-enhance-your-app-with-oasis-rofl-a-quickstart-tutorial-3n55</link>
      <guid>https://dev.to/dc600/how-to-enhance-your-app-with-oasis-rofl-a-quickstart-tutorial-3n55</guid>
      <description>&lt;p&gt;I have mentioned the Oasis ROFL (runtime off-chain logic) framework on several occasions. For most people, this &lt;a href="https://www.youtube.com/watch?v=JFYnEyMFgRE" rel="noopener noreferrer"&gt;explainer video&lt;/a&gt; would be enough. But for developers and dApp builders, who want to try things out themselves, a deeper dive is worth it. In this guide, I will give a quick introduction to ROFL and then share a QuickStart tutorial to help build a ROFL-powered app.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ROFL in a nutshell&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The ROFL architecture consists of these distinct components: the hardware, the application, the remote attestation, the blockchain layers, and user interaction.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw120rnzzlxnj2hwrg6iu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw120rnzzlxnj2hwrg6iu.png" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Further, this 5-part process lays out how ROFL works.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq3i24ftygqc2wqntg497.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq3i24ftygqc2wqntg497.jpeg" alt=" " width="680" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From a developer's perspective, ROFL-powered apps run on Oasis nodes inside a Trusted Execution Environment (TEE), managed through the protocol's unique production-ready EVM runtime - Sapphire.&lt;/p&gt;

&lt;p&gt;When you use ROFL, you get the following support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker-like containers&lt;/strong&gt; or &lt;strong&gt;single executable apps&lt;/strong&gt;, based on what Trusted Compute Base (TCB) you are using, and what your threat model is&lt;/li&gt;
&lt;li&gt;Intel SGX/TDX ensures &lt;strong&gt;privacy and integrity&lt;/strong&gt;, and also provides a full update history and auditability&lt;/li&gt;
&lt;li&gt;Your app is registered, managed, and deployed on a permissionless pool of ROFL nodes, which means it is &lt;strong&gt;not censorable&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;There is a &lt;strong&gt;built-in Key Management Service&lt;/strong&gt; (KMS) that stores your app's secrets as well as secures key derivation inside the TEE&lt;/li&gt;
&lt;li&gt;Verifiable ROFL transactions originating from &lt;strong&gt;integration with Oasis Sapphire&lt;/strong&gt; that enable EVM-compatible confidential smart contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3pktopc68sekzhv4ikc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3pktopc68sekzhv4ikc.png" alt=" " width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, you don't need to build from scratch - you can just wrap your existing app into a ROFL-powered app. Let's see how.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;QuickStart&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There are 5 steps to enhance an app with ROFL power:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialize&lt;/strong&gt; the ROFL manifest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create&lt;/strong&gt; a new app on blockchain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build&lt;/strong&gt; a ROFL bundle&lt;/li&gt;
&lt;li&gt;Encrypt &lt;strong&gt;secrets&lt;/strong&gt; and store them on-chain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy&lt;/strong&gt; your app on a ROFL node&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Containerized App&lt;/strong&gt;&lt;br&gt;
First thing you need is a containerized app with a downloadable Docker-like image. Any public Open Container Initiative (OCI) repository works; however, you might like to choose from &lt;a href="https://docker.io/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; or &lt;a href="https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry" rel="noopener noreferrer"&gt;GitHub container registry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If your app is not already running inside a container and you don't know how, follow this &lt;a href="https://docs.oasis.io/build/rofl/workflow/containerize-app/" rel="noopener noreferrer"&gt;step-by-step mini tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Oasis CLI&lt;/strong&gt;&lt;br&gt;
Next, you need the latest version of the Oasis Command Line Interface (CLI). Install it from &lt;a href="https://docs.oasis.io/build/tools/cli/setup" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tokens&lt;/strong&gt;&lt;br&gt;
Lastly, you will need about &lt;strong&gt;150 tokens&lt;/strong&gt; to cover ROFL registration, renting a machine, and paying for the gas fees. &lt;/p&gt;

&lt;p&gt;Now, you can either create a new account or import an existing one. Let's check out both processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a new account&lt;/strong&gt; -&amp;gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis wallet create my_account &lt;span class="nt"&gt;--file&lt;/span&gt;.algorithm secp256k1-bip44
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later, you can choose to import this account to Metamask or other Ethereum-compatible tooling, e.g. Hardhat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Import an existing account&lt;/strong&gt; -&amp;gt; &lt;br&gt;
You need to export the &lt;strong&gt;secp256k1&lt;/strong&gt; private key or mnemonic from your existing wallet before running this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis wallet import my_account
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you are working in a test environment, you can get free testnet tokens from the official &lt;a href="https://faucet.testnet.oasis.io/" rel="noopener noreferrer"&gt;faucet&lt;/a&gt;. &lt;br&gt;
If you are building on the mainnet, you will need to &lt;a href="https://docs.oasis.io/general/manage-tokens/#get-rose" rel="noopener noreferrer"&gt;buy ROSE&lt;/a&gt; tokens.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Initialize&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is the first step. You start by running &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/rofl#init" rel="noopener noreferrer"&gt;oasis rofl init&lt;/a&gt;&lt;/strong&gt; using &lt;strong&gt;compose.yaml&lt;/strong&gt; inside your app folder. This will generate the ROFL manifest in the form of &lt;strong&gt;rofl.yaml&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, based on your requirement, you can change the &lt;strong&gt;memory&lt;/strong&gt;, specify the number of &lt;strong&gt;cpus&lt;/strong&gt;, and the root filesystem &lt;strong&gt;storage&lt;/strong&gt; section that comes under &lt;strong&gt;resources&lt;/strong&gt;.&lt;br&gt;
&lt;strong&gt;rofl.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;
&lt;span class="na"&gt;tee&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tdx&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;container&lt;/span&gt;
&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt; &lt;span class="c1"&gt;# in megabytes&lt;/span&gt;
  &lt;span class="na"&gt;cpus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;disk-persistent&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt; &lt;span class="c1"&gt;# in megabytes&lt;/span&gt;
&lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;firmware&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/oasisprotocol/oasis-boot/releases/download/v0.6.2/ovmf.tdx.fd#db47100a7d6a0c1f6983be224137c3f8d7cb09b63bb1c7a5ee7829d8e994a42f&lt;/span&gt;
  &lt;span class="na"&gt;kernel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/oasisprotocol/oasis-boot/releases/download/v0.6.2/stage1.bin#e5d4d654ca1fa2c388bf64b23fc6e67815893fc7cb8b7cfee253d87963f54973&lt;/span&gt;
  &lt;span class="na"&gt;stage2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/oasisprotocol/oasis-boot/releases/download/v0.6.2/stage2-podman.tar.bz2#b2ea2a0ca769b6b2d64e3f0c577ee9c08f0bb81a6e33ed5b15b2a7e50ef9a09f&lt;/span&gt;
  &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/oasisprotocol/oasis-sdk/releases/download/rofl-containers%2Fv0.8.0/rofl-containers#08eb5bbe5df26af276d9a72e9fd7353b3a90b7d27e1cf33e276a82dfd551eec6&lt;/span&gt;
    &lt;span class="na"&gt;compose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;compose.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Create&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The next step is to create a new app on-chain. You can use the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/rofl#create" rel="noopener noreferrer"&gt;oasis rofl create&lt;/a&gt;&lt;/strong&gt; command for this.&lt;br&gt;
Please note that any newly created app in this process is registered by default on the Sapphire mainnet. If you are using a test environment, you will need to change the setting. So, you will be required to pass &lt;strong&gt;--network testnet&lt;/strong&gt; parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl create &lt;span class="nt"&gt;--network&lt;/span&gt; testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The check whether this transaction was successful is to find your app on the &lt;a href="https://explorer.oasis.io/testnet/sapphire/rofl/app" rel="noopener noreferrer"&gt;Oasis Explorer&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Build&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this step, we will build the ROFL bundle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command results in the generation of a new .orc file inside your project folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Secrets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is the step where privacy is enforced. So, if there are environment variables that your app is using, you can store them on-chain privately using the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/rofl#secret" rel="noopener noreferrer"&gt;oasis rofl secret&lt;/a&gt;&lt;/strong&gt; command. It would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"my-secret-token"&lt;/span&gt; | oasis rofl secret &lt;span class="nb"&gt;set &lt;/span&gt;TOKEN -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command populates the &lt;strong&gt;TOKEN&lt;/strong&gt; secret. You can now use it in your compose file like this:&lt;br&gt;
&lt;strong&gt;compose.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;python-telegram-bot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ghcr.io/oasisprotocol/demo-rofl-tgbot:ollama"&lt;/span&gt;
    &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;TOKEN=${TOKEN}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to submit the secrets and the ROFL bundle information on-chain, you can do so with the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/rofl#update" rel="noopener noreferrer"&gt;oasis rofl update&lt;/a&gt;&lt;/strong&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Deploy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is the final step of the process. Here, you use the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/rofl#deploy" rel="noopener noreferrer"&gt;oasis rofl deploy&lt;/a&gt;&lt;/strong&gt; command so that your app gets deployed to a ROFL provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command triggers the bootstrapping of a new machine that fits the required resources provided by Oasis. You can check the status of the machine using the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/rofl#machine-show" rel="noopener noreferrer"&gt;oasis rofl machine show&lt;/a&gt;&lt;/strong&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Oasis rofl machine show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now also check your application logs to verify how everything works. You will need the &lt;strong&gt;&lt;a href="https://docs.oasis.io/build/tools/cli/rofl#machine-logs" rel="noopener noreferrer"&gt;oasis rofl machine logs&lt;/a&gt;&lt;/strong&gt; command for this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oasis rofl machine logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Parting words&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are a developer who likes the hands-on approach, I hope you had a good time trying out this tutorial and successfully deploying your first ROFL-powered app. &lt;br&gt;
You will note that in this guide, I have provided several links to the Oasis documentation instead of elaborating on them. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;containerize your app &lt;/li&gt;
&lt;li&gt;latest Oasis CLI release&lt;/li&gt;
&lt;li&gt;oasis rofl init&lt;/li&gt;
&lt;li&gt;oasis rofl create&lt;/li&gt;
&lt;li&gt;oasis rofl secret&lt;/li&gt;
&lt;li&gt;oasis rofl update&lt;/li&gt;
&lt;li&gt;oasis rofl deploy&lt;/li&gt;
&lt;li&gt;oasis rofl machine show&lt;/li&gt;
&lt;li&gt;oasis rofl machine logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's because I wanted to focus on the topic here without going into details on these commands, which require separate attention, and I will prepare other tutorials explaining them later on. &lt;/p&gt;

&lt;p&gt;For a quick chat with the Oasis engineering team for help with specific issues, you can drop your comments in the &lt;strong&gt;dev-central channel&lt;/strong&gt; in the official &lt;a href="https://discord.com/invite/BQCxwhT5wS" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>blockchain</category>
      <category>tee</category>
      <category>devex</category>
    </item>
  </channel>
</rss>
