<?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>Forem: Claude Barde</title>
    <description>The latest articles on Forem by Claude Barde (@claudebarde).</description>
    <link>https://forem.com/claudebarde</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F120466%2Fbf3f8e54-20db-4c7c-912c-d95dc4cb192b.jpeg</url>
      <title>Forem: Claude Barde</title>
      <link>https://forem.com/claudebarde</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/claudebarde"/>
    <language>en</language>
    <item>
      <title>Introduction to the FungibleToken contract on Midnight</title>
      <dc:creator>Claude Barde</dc:creator>
      <pubDate>Thu, 11 Sep 2025 14:35:44 +0000</pubDate>
      <link>https://forem.com/devsofmidnight/introduction-to-the-fungibletoken-contract-on-midnight-20ai</link>
      <guid>https://forem.com/devsofmidnight/introduction-to-the-fungibletoken-contract-on-midnight-20ai</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction to the FungibleToken contract on Midnight&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Midnight&lt;/strong&gt; is a privacy-first blockchain designed to bring &lt;em&gt;privacy&lt;/em&gt; to decentralized applications. It achieves this through &lt;a href="https://docs.midnight.network/develop/how-midnight-works/" rel="noopener noreferrer"&gt;zero-knowledge proofs, programmable data protection, and developer-friendly tools&lt;/a&gt; like &lt;strong&gt;Compact&lt;/strong&gt;, a TypeScript-based DSL (Domain-Specific Language) for writing privacy-aware smart contracts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.openzeppelin.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenZeppelin&lt;/strong&gt;&lt;/a&gt; is renowned in the Ethereum ecosystem for its battle-tested smart contract libraries, which have secured trillions in on-chain value. Recently, &lt;a href="https://midnight.network/blog/openzeppelin-joins-forces-with-midnight-to-shape-the-future-of-privacy-preserving-smart" rel="noopener noreferrer"&gt;OpenZeppelin partnered with Midnight&lt;/a&gt; to bring comparable tooling to the Compact ecosystem, adapting familiar standards like ERC-20 into privacy-preserving variants.&lt;/p&gt;

&lt;p&gt;In the Ethereum world, the &lt;strong&gt;ERC-20&lt;/strong&gt; standard defines a fungible token with public ledger functions like &lt;code&gt;balanceOf&lt;/code&gt;, &lt;code&gt;transfer&lt;/code&gt;, &lt;code&gt;approve&lt;/code&gt;, etc. It exposes transaction data transparently and lacks built-in privacy. The &lt;strong&gt;FungibleToken&lt;/strong&gt; contract on Midnight draws inspiration from this, but operates within Midnight’s zero-knowledge, selective-disclosure framework.&lt;/p&gt;

&lt;p&gt;Fungible tokens are a cornerstone of the blockchain ecosystem, representing digital assets that are interchangeable – much like traditional currency. On various blockchains, these tokens power a wide array of applications, from facilitating seamless transactions and enabling decentralized finance (DeFi) protocols to representing ownership in digital communities and driving the mechanics of in-game economies. &lt;/p&gt;

&lt;p&gt;Unlike unique non-fungible tokens (NFTs), the value of one fungible token is identical to another of the same type, making them ideal for use cases requiring divisibility and ease of exchange. Their widespread adoption underscores their importance in building liquid and interconnected digital economies.&lt;/p&gt;

&lt;p&gt;In this article, you'll learn about the core features of the contract, including how it manages ledger state variables, its key entry points and circuits for operations like minting, burning, and transferring tokens, and the essential safety and utility functions provided by the &lt;strong&gt;Utils&lt;/strong&gt; and &lt;strong&gt;Initializable&lt;/strong&gt; modules.&lt;br&gt;&lt;br&gt;
By understanding how these components fit together, you’ll gain insight into how the &lt;strong&gt;FungibleToken&lt;/strong&gt; contract balances fungibility, usability, and privacy, providing an essential building block for privacy-preserving DeFi, identity, and tokenized assets on Midnight.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Features of the FungibleToken Contract&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The FungibleToken contract on Midnight utilizes ledger state variables to keep track of balances, allowances, total supply, name, symbol, and decimals. Its functionality is exposed through "circuits" (entry points) like &lt;code&gt;Mint&lt;/code&gt;, &lt;code&gt;Burn&lt;/code&gt;, &lt;code&gt;Transfer&lt;/code&gt;, &lt;code&gt;Approve&lt;/code&gt;, &lt;code&gt;TransferFrom&lt;/code&gt;, and &lt;code&gt;Initialize&lt;/code&gt;, all of which enforce specific zero-knowledge validated transitions and maintain the integrity of the token's state.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;1. Ledger State Variables&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In Compact, the contract defines a structured &lt;strong&gt;state&lt;/strong&gt; storing token balances and allowances—similar to ERC-20. The &lt;code&gt;_balances&lt;/code&gt; map keeps track of the users’ token balances and is updated when a transfer occurs. The &lt;code&gt;_allowances&lt;/code&gt; map keeps track of the permission given to specific users to spend tokens on behalf of another user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;ledger&lt;/span&gt; &lt;span class="nx"&gt;_balances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ZswapCoinPublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ContractAddress&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Uint&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;ledger&lt;/span&gt; &lt;span class="nx"&gt;_allowances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ZswapCoinPublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ContractAddress&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ZswapCoinPublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ContractAddress&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Uint&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values live in the contract's ledger and are updated through transactions sent to the contract.&lt;/p&gt;

&lt;p&gt;There are other values in the ledger that are set when the contract is deployed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;ledger&lt;/span&gt; &lt;span class="nx"&gt;_totalSupply&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Uint&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;sealed&lt;/span&gt; &lt;span class="nx"&gt;ledger&lt;/span&gt; &lt;span class="nx"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Opaque&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;sealed&lt;/span&gt; &lt;span class="nx"&gt;ledger&lt;/span&gt; &lt;span class="nx"&gt;_symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Opaque&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;sealed&lt;/span&gt; &lt;span class="nx"&gt;ledger&lt;/span&gt; &lt;span class="nx"&gt;_decimals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Uint&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values provide different information about the token managed by the contract, its total supply, its name, its symbol, and its decimal (for display).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Entry Points and Circuits&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In Compact, entry points are defined as &lt;strong&gt;circuits&lt;/strong&gt; (akin to Solidity functions), each modelling a zero-knowledge validated transition. The difference between a circuit entry point and a circuit is that the entry point is callable via a transaction, while the non-entry point circuit is internal. Core circuits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Mint&lt;/code&gt; / &lt;code&gt;Burn&lt;/code&gt;&lt;/strong&gt; (to mint new tokens or burn existing tokens).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Transfer&lt;/code&gt;&lt;/strong&gt;: to move tokens between addresses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Approve&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;TransferFrom&lt;/code&gt;&lt;/strong&gt;: standard ERC-20-style delegation mechanisms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Initialize&lt;/code&gt;&lt;/strong&gt;: via the &lt;strong&gt;Initializable&lt;/strong&gt; module for contract setup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each circuit enforces necessary constraints — for example, ensuring sufficient balance, managing allowance decrements, and preserving total supply.&lt;/p&gt;

&lt;p&gt;In the next step of the contract lifecycle, the different metadata stored in the ledger of the contract are safely initialized.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Initialization &amp;amp; metadata&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The following circuits define the essential setup and retrieval logic for the fungible token metadata and users’ balances, enforcing correct initialization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;initialize(name_, symbol_, decimals_)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
One-time setup. Calls &lt;code&gt;Initializable_initialize()&lt;/code&gt;, then stores the (disclosed) name, symbol, and decimals. Every other public circuit asserts that the contract is initialized first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;name()&lt;/code&gt; / &lt;code&gt;symbol()&lt;/code&gt; / &lt;code&gt;decimals()&lt;/code&gt; / &lt;code&gt;totalSupply()&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Simple getters that first assert initialized, then return the sealed (read only) ledger values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;balanceOf(account)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Safe map lookup that returns &lt;code&gt;0&lt;/code&gt; if the account isn’t present (to prevent contract failure if the key is absent).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The transfer family&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;FungibleToken&lt;/code&gt; contract's &lt;strong&gt;transfer&lt;/strong&gt; circuits manage token movement. Key circuits include: &lt;code&gt;transfer&lt;/code&gt; for safe user-initiated transfers, &lt;code&gt;_unsafeTransfer&lt;/code&gt; for internal token movement, &lt;code&gt;_transfer&lt;/code&gt; for administrative transfers, &lt;code&gt;_unsafeUncheckedTransfer&lt;/code&gt; for low-level token movement, and &lt;code&gt;_update&lt;/code&gt; as the central accounting function for all token operations.&lt;/p&gt;

&lt;p&gt;These are split into &lt;strong&gt;safe&lt;/strong&gt; and &lt;strong&gt;unsafe&lt;/strong&gt; variants because &lt;strong&gt;sending to contract addresses is currently disallowed&lt;/strong&gt; (until contract-to-contract interactions are supported). &lt;/p&gt;

&lt;p&gt;“Safe” circuits enforce that policy; “unsafe” ones let you bypass it—explicitly marked as dangerous in comments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;transfer(to, value)&lt;/code&gt; → &lt;code&gt;Boolean&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Safe user-initiated transfer: rejects if &lt;code&gt;to&lt;/code&gt; is a &lt;code&gt;ContractAddress&lt;/code&gt;. Internally, it just forwards to the unsafe variant after the check.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_unsafeTransfer(to, value)&lt;/code&gt; → &lt;code&gt;Boolean&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Owner is the caller (&lt;code&gt;left(ownPublicKey())&lt;/code&gt;). Moves value using the unchecked internal mover, then returns &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_transfer(from, to, value)&lt;/code&gt; → &lt;code&gt;[]&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Admin/extension hook that moves tokens &lt;strong&gt;from an arbitrary &lt;code&gt;from&lt;/code&gt;&lt;/strong&gt; (not necessarily the caller). Still enforces the “no contracts as &lt;code&gt;to&lt;/code&gt;” rule and then uses the same mover underneath.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_unsafeUncheckedTransfer(from, to, value)&lt;/code&gt; → &lt;code&gt;[]&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The low-level mover checks that neither side is the zero/burn address and then delegates the actual accounting to &lt;code&gt;_update&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;_update(from, to, value)&lt;/code&gt; → &lt;code&gt;[]&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Central accounting function&lt;/strong&gt; used by all mint/burn/transfer paths. It’s an internal circuit; it cannot be called via a transaction.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;from&lt;/code&gt; is zero, the &lt;strong&gt;mint&lt;/strong&gt; circuit is called, it asserts no &lt;code&gt;uint128&lt;/code&gt; overflow, and increases &lt;code&gt;_totalSupply&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Else, it deducts from &lt;code&gt;from&lt;/code&gt; balance (or reverts on insufficient funds).&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;to&lt;/code&gt; is zero, the &lt;strong&gt;burn&lt;/strong&gt; circuit is called, and it decreases &lt;code&gt;_totalSupply&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Else, it adds to &lt;code&gt;to&lt;/code&gt; balance.
This single function guarantees the invariants for every movement of value.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The "transfer family" circuits ensure secure token movement, with "safe" variants disallowing transfers to contract addresses and "unsafe" variants providing lower-level control.&lt;br&gt;&lt;br&gt;
This leads us to explore how allowances function, enabling delegated token spending.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Allowances (approve / spend / transferFrom)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This section details the allowance mechanisms within the FungibleToken contract, which enable users to delegate spending permissions to other addresses. These circuits facilitate secure, approved transfers on behalf of an owner without directly exposing their private keys.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;allowance(owner, spender)&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Read the nested &lt;code&gt;_allowances&lt;/code&gt; map, returning &lt;code&gt;0&lt;/code&gt; when keys are missing (no revert).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;approve(spender, value)&lt;/code&gt; → &lt;code&gt;Boolean&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The owner is the caller. Forwards to &lt;code&gt;_approve(owner, spender, value)&lt;/code&gt; and returns &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;transferFrom(from, to, value)&lt;/code&gt; → &lt;code&gt;Boolean&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Safe delegated transfer: enforces the “no contract receiver” rule, then defers to &lt;code&gt;_unsafeTransferFrom&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_unsafeTransferFrom(from, to, value)&lt;/code&gt; → &lt;code&gt;Boolean&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The spender is the caller. First spends allowance via &lt;code&gt;_spendAllowance(from, spender, value)&lt;/code&gt;, then moves value using &lt;code&gt;_unsafeUncheckedTransfer&lt;/code&gt;. Returns &lt;code&gt;true&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_approve(owner, spender, value)&lt;/code&gt; → &lt;code&gt;[]&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It ensures that both the owner and the spender are valid, creates the owner’s entry in the map if needed, and then writes the allowance. (This mirrors OZ’s ERC-20 pattern of public &lt;code&gt;approve()&lt;/code&gt; → internal &lt;code&gt;_approve()&lt;/code&gt;.) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_spendAllowance(owner, spender, value)&lt;/code&gt; → &lt;code&gt;[]&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It deducts from the allowance unless it’s “infinite.” The implementation treats &lt;strong&gt;&lt;code&gt;MAX_UINT128&lt;/code&gt;&lt;/strong&gt; as infinite: if &lt;code&gt;currentAllowance == MAX&lt;/code&gt;, it doesn’t decrement; otherwise, it asserts &lt;code&gt;currentAllowance ≥ value&lt;/code&gt; and writes back &lt;code&gt;currentAllowance - value&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
This is important because it supports “no-friction approvals” by letting apps set MAX once. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, we just covered how allowances let people delegate token spending—basically, giving others permission to move their tokens. Up next, we'll dive into how we create and delete tokens in the contract.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Minting and burning&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here's how the FungibleToken contract handles making and destroying tokens. We'll dive into the &lt;code&gt;_mint&lt;/code&gt; and &lt;code&gt;_burn&lt;/code&gt; functions, showing what they do and how they link up with the main accounting system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_mint(account, value)&lt;/code&gt;&lt;/strong&gt; (safe) → &lt;code&gt;[]&lt;/code&gt;&lt;br&gt;&lt;br&gt;
It forbids minting &lt;strong&gt;to&lt;/strong&gt; a contract address (same contract-to-contract restriction), then forwards to &lt;code&gt;_unsafeMint&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_unsafeMint(account, value)&lt;/code&gt;&lt;/strong&gt; → &lt;code&gt;[]&lt;/code&gt;&lt;br&gt;&lt;br&gt;
It validates the receiver’s address, then calls &lt;code&gt;_update(burnAddress(), account, value)&lt;/code&gt;—i.e., mint is modelled as a transfer &lt;strong&gt;from&lt;/strong&gt; the burn/zero address. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;_burn(account, value)&lt;/code&gt;&lt;/strong&gt; → &lt;code&gt;[]&lt;/code&gt;&lt;br&gt;&lt;br&gt;
It validates the sender’s address, then calls &lt;code&gt;_update(account, burnAddress(), value)&lt;/code&gt;—i.e., burn is a transfer &lt;strong&gt;to&lt;/strong&gt; the burn/zero address.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Note:&lt;/em&gt; The actual notion of “zero/burn” address is standardized in the Utils module; you can also see helpers like &lt;code&gt;Utils_isKeyOrAddressZero&lt;/code&gt; and &lt;code&gt;Utils_isContractAddress&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because mint and burn also route through &lt;code&gt;_update&lt;/code&gt;, &lt;strong&gt;total supply is adjusted in exactly one place,&lt;/strong&gt; and the same safety checks apply across all flows (including the &lt;code&gt;uint128&lt;/code&gt; overflow check on mint). &lt;/p&gt;

&lt;p&gt;The mint and burn circuits, by using the &lt;code&gt;_update&lt;/code&gt; function, make sure the total supply adjustments are always consistent and that all token flows get the same safety checks.&lt;br&gt;&lt;br&gt;
Now, let's dive into the extra safety and utility stuff that the &lt;code&gt;Utils&lt;/code&gt; and &lt;code&gt;Initializable&lt;/code&gt; modules bring to the table.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Safety &amp;amp; utility glue (from &lt;code&gt;Utils&lt;/code&gt; and &lt;code&gt;Initializable&lt;/code&gt;)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This section explores how the &lt;code&gt;Utils&lt;/code&gt; and &lt;code&gt;Initializable&lt;/code&gt; modules provide essential safeguards and helpful functionalities. These components are vital for ensuring the contract's integrity and enabling secure, well-managed operations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initialization guards&lt;/strong&gt;: The &lt;code&gt;Initializable_initialize&lt;/code&gt; and &lt;code&gt;Initializable_assertInitialized&lt;/code&gt; functions serve as crucial initialization guards within the &lt;code&gt;Initializable&lt;/code&gt; contract. These safeguards ensure that a contract's state is properly set up only once and that subsequent operations only proceed if the contract has been correctly initialized. Every circuit that interacts with or modifies the contract's state is designed to invoke the &lt;code&gt;assert&lt;/code&gt; function, reinforcing the integrity of the initialization process. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Address helpers&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Utils_isContractAddress(either)&lt;/code&gt; distinguishes user keys from contract addresses.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Utils_isKeyOrAddressZero(either)&lt;/code&gt; detects the zero/burn address used in &lt;code&gt;_update&lt;/code&gt;, &lt;code&gt;_unsafeUncheckedTransfer&lt;/code&gt;, etc.
These support the temporary “no contract receiver” policy and zero-address checks. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Utils&lt;/strong&gt; and &lt;strong&gt;Initializable&lt;/strong&gt; modules provide crucial safety and utility functions, ensuring the contract's proper setup and secure operation. Now, let's look at how all these different parts of the &lt;strong&gt;FungibleToken&lt;/strong&gt; contract work together.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How the pieces fit together&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This part shows how everything in the FungibleToken contract is hooked up. Whether it's you sending tokens, someone else doing it for you, or tokens being created or destroyed, it all funnels through a few key functions and ultimately lands in the main &lt;code&gt;_update&lt;/code&gt; function to keep track of everything.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;User transfer:&lt;br&gt;&lt;br&gt;
&lt;code&gt;transfer&lt;/code&gt; → &lt;em&gt;(safe check)&lt;/em&gt; → &lt;code&gt;_unsafeTransfer&lt;/code&gt; → &lt;code&gt;_unsafeUncheckedTransfer&lt;/code&gt; → &lt;code&gt;_update&lt;/code&gt; (balances/supply) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delegated transfer:&lt;br&gt;&lt;br&gt;
&lt;code&gt;transferFrom&lt;/code&gt; → &lt;em&gt;(safe check)&lt;/em&gt; → &lt;code&gt;_unsafeTransferFrom&lt;/code&gt; → &lt;code&gt;_spendAllowance&lt;/code&gt; → &lt;code&gt;_unsafeUncheckedTransfer&lt;/code&gt; → &lt;code&gt;_update&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mint/Burn:&lt;br&gt;&lt;br&gt;
&lt;code&gt;_mint/_unsafeMint&lt;/code&gt; or &lt;code&gt;_burn&lt;/code&gt; → &lt;code&gt;_update&lt;/code&gt; (with zero/burn address on one side) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This section illustrates how various token operations, from user transfers to minting and burning, ultimately funnel through the central &lt;code&gt;_update&lt;/code&gt; function for consistent accounting. Now, let's summarize the key takeaways of the &lt;strong&gt;FungibleToken&lt;/strong&gt; contract on Midnight.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;FungibleToken&lt;/strong&gt; Compact contract on Midnight is a privacy-aware reimagining of the ERC-20 standard. It maintains the familiar token interfaces—balances, transfers, approvals—but encodes them as ZK-validated circuits within Compact, enabling private, verifiable execution. The contract’s state and logic are shielded by design, exposing only proofs rather than raw data to the blockchain. &lt;/p&gt;

&lt;p&gt;The ERC-20 standard revolutionized the crypto landscape by providing a common framework for creating and managing digital assets, fostering interoperability, and accelerating the growth of decentralized applications. For Midnight, an ERC-20-based token is crucial as it leverages this established standard while integrating ZK-privacy, offering a familiar yet enhanced experience for developers and users seeking both functionality and confidentiality.&lt;/p&gt;

&lt;p&gt;This model contrasts sharply with ERC-20 on Ethereum, where all token movements and balances are fully transparent. Here, Midnight allows selective disclosure: users and applications choose what to reveal. The &lt;strong&gt;FungibleToken&lt;/strong&gt; contract thus balances fungibility, usability, and privacy—providing an essential building block for privacy-preserving DeFi, identity, and tokenized assets on Midnight.&lt;/p&gt;




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

&lt;p&gt;Delve deeper into the code, contracts, and comprehensive documentation to enhance your understanding and development skills. These resources are invaluable for building robust and innovative solutions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FungibleToken contract: &lt;a href="https://github.com/OpenZeppelin/compact-contracts/blob/main/contracts/fungibleToken/src/FungibleToken.compact" rel="noopener noreferrer"&gt;FungibleToken.compact on Github&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;OpenZeppelin documentation: &lt;a href="https://docs.openzeppelin.com/contracts-compact/0.0.1/fungibletoken" rel="noopener noreferrer"&gt;docs.openzeppelin.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ERC20 standard: &lt;a href="https://ethereum.org/en/developers/docs/standards/tokens/erc-20/" rel="noopener noreferrer"&gt;ethereum.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Midnight docs: &lt;a href="https://docs.midnight.network/" rel="noopener noreferrer"&gt;Midnight Developer Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Do you have any questions?: &lt;a href="https://forum.midnight.network/" rel="noopener noreferrer"&gt;Midnight Forum&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>midnight</category>
      <category>compact</category>
    </item>
    <item>
      <title>Get Married on the Blockchain!</title>
      <dc:creator>Claude Barde</dc:creator>
      <pubDate>Fri, 22 Mar 2019 07:42:22 +0000</pubDate>
      <link>https://forem.com/claudebarde/get-married-on-the-blockchain-28ef</link>
      <guid>https://forem.com/claudebarde/get-married-on-the-blockchain-28ef</guid>
      <description>&lt;h4&gt;
  
  
  Or how the blockchain can also revolutionize our relationships…
&lt;/h4&gt;

&lt;p&gt;Since the moment I heard about it, I have always been fascinated by the huge possibilities that smart contracts give us and I feel that they are still underestimated.&lt;/p&gt;

&lt;p&gt;I started getting interested in Bitcoin almost two years ago but it's only a few months ago I discovered the Ethereum blockchain and Solidity. Since then, I haven't been able to stop myself from reading everything I can about the subject. I subscribed to mailing lists to receive articles about Ethereum and Solidity directly in my mailbox, I often take a peek at the Solidity docs and I read countless tutorials about the subject.&lt;/p&gt;

&lt;p&gt;However, it looks like outside big companies, there aren't a lot of people out there who try to use the Ethereum blockchain in a more "disruptive" way. Most of the tutorials teach how to create ERC20 tokens or voting systems. I often let my mind wander and imagine what we could achieve if the blockchain would replace our governments. Which tasks could smart contracts allow us to take back and own again? That's how the idea of writing marriage certificate smart contracts came to me. After all, it is something relatively simple: two human beings want to be wed (for better or for worse), they register their union in front of an authority and they go back to the same authority for instance when they need to prove their marriage or when they want to divorce.&lt;/p&gt;

&lt;p&gt;In real life, a marriage is a real challenge and people often end up wasting a lot of time and money. A smart contract can help them get married (or divorced) in a matter of seconds for a few cents. The immutability of the blockchain allows making sure the marriage certificate is not altered beyond its inner functions and makes it available anywhere at any time.&lt;/p&gt;

&lt;p&gt;This is how the idea of celebrating marriages on the blockchain was born! Through the website, couples can create a smart contract that will store their personal identity information (like names, location and ID number) in an immutable fashion to be able to prove ownership of the certificate in a simple way, they can without efforts update the status of the marriage (a divorce would literally take seconds and a few cents to perform) and finally, the design of the smart contract allows couples to use the certificate to store common funds in two different ways: a "joint account" where each spouse can freely deposit and withdraw money and a "savings account" where the agreement of both spouses is required before withdrawing funds.&lt;/p&gt;

&lt;p&gt;I will describe below the code of the smart contract (available at this address), function after function, in order to give a better understanding of what it does but also to receive useful feedback :) It may also be useful for beginners as I was a few months ago to get a detailed walk-through of how a smart contract works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Marriage Certificate Factory
&lt;/h2&gt;

&lt;p&gt;Every marriage certificate is created by a factory smart contract that is in charge of setting the right state with the right data and savings the certificates addresses. As it is customary, the smart contract starts with the version pragma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.5.0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The smart contract uses the latest version of Solidity compared to a lot of smart contracts written in the fourth version.&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;contract&lt;/span&gt; &lt;span class="nx"&gt;MarriageCertificateCreator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;MarriageCertificate&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;certificates&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="nx"&gt;payable&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;uint&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;certificateFee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;lastMarriage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the contract declaration. It creates four state variables: a &lt;strong&gt;certificates&lt;/strong&gt; variable (a dynamic array containing values of type "MarriageCertificate") which ultimately will contain the addresses of every certificate created, an &lt;strong&gt;owner&lt;/strong&gt; variable (to use various functions of the smart contract), a &lt;strong&gt;certificateFee&lt;/strong&gt; variable (an unsigned integer representing the fee in wei) and a &lt;strong&gt;lastMarriage&lt;/strong&gt; variable (an array of 3 strings that will hold the names and location from the last registered certificate).&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="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;certificateFee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000000000000000&lt;/span&gt; &lt;span class="nx"&gt;wei&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The constructor is pretty straight forward, it saves the owner's address (mine) and sets the fee for the creation of a new marriage certificate to 0.1 ether. This fee can be manually updated in another function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event NewCertificateCreated(
    MarriageCertificate newCertificateAddress, uint numberOfCertificates
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the only event in this smart contract, it is emitted every time a new certificate is created and returns the address of the new contract and the total number of marriage certificates to the web3 interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The createNewCertificate function
&lt;/h2&gt;

&lt;p&gt;This is where all the magic happens! The following function is in charge of receiving the data from the web3 interface, of validating them, of updating the state of the contract factory and obviously of creating the new marriage certificate.&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2ApFwzLf1c1NHgBtJ419JRaQ.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2ApFwzLf1c1NHgBtJ419JRaQ.png" title="createNewCertificate function" alt="alt text" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will find below a breakdown of the different parts of this function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createNewCertificate(
    string memory spouse1, string memory spouse2, address spouse2address, string memory location
    ) public payable {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function accepts 4 arguments:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;spouse1&lt;/strong&gt; variable is a JavaScript object in JSON format that contains various information about the first spouse (who is also the initiator of the marriage certificate). A JSON string is a better choice to store in the smart contract for multiple reasons: it allows to store different information in the future, it is easier to deal with in Solidity than other structures like array or structs, it is easier to fetch from the web3 interface (no need to convert it if it was, for example, a struct) and most of the information provided during the smart contract creation is not vital for its execution.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;spouse2&lt;/strong&gt; variable is also a JavaScript object in JSON format that holds the information relative to the second spouse. As the marriage certificate is created by one person, the second actor must validate the information later to make the marriage valid. The marriage stays in a permanent invalid state until the second spouse comes and approves the marriage.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;spouse2address&lt;/strong&gt; variable contains the address of the second spouse who must approve the marriage. The two addresses will be stored independently as they are required to update the state of the newly created certificate.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;location&lt;/strong&gt; variable is a Javascript object in JSON format holding the names of the city and the country chosen by the couple for the registration process.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MarriageCertificate newCertificate = 
    new MarriageCertificate(
        msg.sender,
        spouse1,
        spouse2,
        spouse2address,
        location
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The body of the function is responsible for passing down the arguments received earlier, the &lt;strong&gt;msg.sender&lt;/strong&gt; being the address of &lt;strong&gt;spouse1&lt;/strong&gt;. Note that whoever creates the marriage certificate will be considered as the first spouse, whatever value is passed in the spouse1 variable.&lt;br&gt;
Note also that in Solidity 0.5, when you create a new smart contract from a smart contract, the value it returns is ultimately an address but it will be of type "NameOfCreatedSmartContract". This is also important to know as we will store these values in an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;certificates.push(newCertificate);
lastMarriage = [spouse1, spouse2, location];
emit NewCertificateCreated(newCertificate, certificates.length);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next lines of code are pretty straight forward: we push the address of the new certificate into the &lt;em&gt;certificates&lt;/em&gt; array (whose values must be of type "NameOfCreatedSmartContract" as per Solidity 0.5), we update the lastMarriage variable so the value is always set to the last registered marriage and we emit an event that will be caught by the web3 interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Marriage Certificate
&lt;/h2&gt;

&lt;p&gt;The Marriage Certificate smart contract is a pretty simple one as it is mostly used to store immutable information about the two spouses, mutable information about the status of the marriage and common funds in two separate accounts, plus a couple of functions to deposit and withdraw the abovementioned funds.&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2ArWlJFzpni5FxJBBah1VttA.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2ArWlJFzpni5FxJBBah1VttA.png" title="The Marriage Certificate contract instanciation" alt="alt text" width="800" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few variables are set during the creation of the contract as well as two event emitters: &lt;strong&gt;location&lt;/strong&gt;, &lt;strong&gt;spouse1&lt;/strong&gt; and &lt;strong&gt;spouse2&lt;/strong&gt; will hold the information about the spouses and the place of registration. It should be noted that the ID numbers provided by the spouses during the certificate creation are encrypted client-side and a decryption key is provided, should the spouses have to prove they are the ones who registered the marriage.&lt;br&gt;
The &lt;strong&gt;isValid&lt;/strong&gt; variable is an array of 2 booleans representing the marriage status chosen by each spouse, &lt;strong&gt;spousesAddresses&lt;/strong&gt; is an array of two addresses containing the spouses' addresses mostly used in require functions to make sure the status of the contract can only be modified by the two spouses. &lt;br&gt;
The &lt;strong&gt;timestamp&lt;/strong&gt; variable holds the creation timestamp and the &lt;strong&gt;accounts&lt;/strong&gt; mapping keeps track of the amount of ether in the "joint" and "savings" account. &lt;br&gt;
A &lt;strong&gt;withdrawRequestFromSavings&lt;/strong&gt; struct will be created every time one of the spouses makes a withdrawal request from the savings account. The request is then saved in the &lt;strong&gt;withdrawRequests&lt;/strong&gt; mapping.&lt;br&gt;
Finally, the &lt;strong&gt;MarriageValidity&lt;/strong&gt; event returns the isValid array and the &lt;strong&gt;NewWithdrawalRequestFromSavings&lt;/strong&gt; event returns the newly created request.&lt;/p&gt;
&lt;h3&gt;
  
  
  The constructor
&lt;/h3&gt;

&lt;p&gt;The constructor function is pretty standard:&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2Awbg1Os5syxLwVgZaqCJOtw.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2Awbg1Os5syxLwVgZaqCJOtw.png" title="Marriage Certificate constructor" alt="alt text" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It receives different information about the newlywed couple, stores it in the variables created earlier and set the "joint" and "savings" accounts to 0. The isValid variable is set to &lt;code&gt;[true, false]&lt;/code&gt; as the marriage can only be valid after the second spouse approves it.&lt;/p&gt;
&lt;h3&gt;
  
  
  The contract state manipulations
&lt;/h3&gt;

&lt;p&gt;The smart contract allows the spouses to update the status of the marriage as they wish. The status is calculated using a boolean operation with the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; operator between the two values in the &lt;em&gt;isValid&lt;/em&gt; array. This means that, for the marriage to be valid, both spouses must agree with it. A simple reading of the boolean values in the &lt;em&gt;isValid&lt;/em&gt; array can also indicate which spouse agrees or disagrees with the marriage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;modifier onlySpouses {
        require (
            msg.sender == spousesAddresses[0] || msg.sender == spousesAddresses[1], "The contract status can only be changed by one of the spouses."
            );
        _;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This modifier will be used a couple of times and makes sure that the person updating the state of the smart contract does it from one of the two addresses that were provided during its creation.&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2A2Efd-g8LEocKcIqVje-r3Q.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2A2Efd-g8LEocKcIqVje-r3Q.png" title="changeMarriageStatus function" alt="alt text" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;changeMarriageStatus&lt;/em&gt; function does a simple boolean flip when one of the spouses asks for a change in the marriage status. Note that both spouses must set both values in the &lt;em&gt;isValid&lt;/em&gt; array to &lt;code&gt;true&lt;/code&gt; in order for the divorce to be effective.&lt;/p&gt;

&lt;h3&gt;
  
  
  The deposit/withdrawal functions
&lt;/h3&gt;

&lt;p&gt;A smart contract being basically an Ethereum account with code, it would be a pity not to use this functionality :) To push it further, the marriage certificate is divided into two different accounts: a "joint" account and a "savings" account.&lt;br&gt;
The "joint" account is an account where both spouses (or anyone else with an Ethereum address for that matter) can send ether and both spouses can withdraw as much as they want.&lt;br&gt;
The "savings" account is an account where only the two spouses can send money to and in order to withdraw money, the initiator of the withdrawal must register a request that will have then to be approved by the second spouse.&lt;/p&gt;

&lt;p&gt;Let's dive into the code:&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2Ax_gAwcDZifYAp2ounkNG3A.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2Ax_gAwcDZifYAp2ounkNG3A.png" title="deposit function" alt="alt text" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;deposit&lt;/strong&gt; function  allows the spouses to deposit money through the web interface. It accepts 2 parameters: the &lt;em&gt;amount&lt;/em&gt; to be added and the name of the &lt;em&gt;account&lt;/em&gt; to increment. The &lt;em&gt;onlySpouses&lt;/em&gt; modifier makes sure only the two spouses have access to this function.&lt;/p&gt;

&lt;p&gt;As a safety measure, the contract verifies that the amount selected by the user is also the amount that was sent. The stringsAreEqual function checks the bytes32 variable and the contract decides to increment the joint or the savings account accordingly. The last &lt;em&gt;assert&lt;/em&gt; function is there to check that whatever happens, the sum of the joint account and the savings account is always equal to the total balance of the contract.&lt;/p&gt;

&lt;p&gt;Every change in balance that goes through the functions of the smart contract emits a &lt;em&gt;LogBalance&lt;/em&gt; event with the total balance, the balance of the "joint account" and the balance of the "savings balance".&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2AVGNjNc1xArF_dln6aizD4g.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2AVGNjNc1xArF_dln6aizD4g.png" title="withdraw function" alt="alt text" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;withdraw&lt;/strong&gt; function is a bit more intricate. None of the spouses is allowed to withdraw money from the savings account without the approval of the second one and this function must make sure it doesn't happen.&lt;br&gt;
If one of them sends a transaction to withdraw ether from the savings account, a request is saved in the contract and a request ID is issued. The second spouse must use his/her own account address to approve the request.&lt;/p&gt;

&lt;p&gt;First of all, the &lt;em&gt;onlySpouses&lt;/em&gt; modifier ensures that no one other but the two spouses can withdraw money from the contract. The contract then checks if the requested amount doesn't exceed the balance in the selected account.&lt;br&gt;
The first condition verifies the name of the selected account and checks the requested amount to be sure it doesn't exceed the balance of the account.&lt;/p&gt;

&lt;p&gt;If the "joint" account is chosen, the result is straightforward: the amount is deducted from the balance and sent to the sender.&lt;/p&gt;

&lt;p&gt;If the "savings" account is chosen, the contract creates a (pseudo) unique ID adding the current timestamp, the block difficulty and the block number. As it is very unlikely that two requests come exactly at the same time, this should suffice. A new struct of type &lt;em&gt;withdrawRequestFromSavings&lt;/em&gt; is created and saved in the &lt;em&gt;withdrawRequests&lt;/em&gt; mapping using the ID as a key. Once the new request is saved in the mapping, we emit an event to fetch the request ID in the web interface.&lt;/p&gt;

&lt;p&gt;To finish, we check once again that the joint account balance and the savings account balance equal the total balance and the contract is reverted to its previous state if it isn't the case.&lt;br&gt;
Now let's have a look at the function allowing the spouses to approve withdrawal requests from the savings account and sending the funds.&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2Auzjst2OgNS2oPvg_m8LjLA.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2Auzjst2OgNS2oPvg_m8LjLA.png" title="approveWithdrawRequestFromSavings function" alt="alt text" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;approveWithdrawRequestFromSavings&lt;/strong&gt; function takes the request ID as a parameter. The function can only be accessed by one of the spouses. The contract fetches the request from the mapping in storage and runs a few checks: by checking the timestamp and the amount, it makes sure the request exists (they will be equal to 0 by default if the request struct was not found), then it checks whether the requested amount is still available and whether the request is still pending (it wouldn't make sense to approve a request that's already approved!)&lt;/p&gt;

&lt;p&gt;If the request is pending, the next condition ensures that the spouse approving the request is NOT the one who created it (users trying to approve a request they created themselves will trigger the revert function).&lt;br&gt;
If everything is all right, the request is marked as approved (&lt;code&gt;true&lt;/code&gt;), the requested amount is deducted from the savings account and sent to the spouse who initiated the request.&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2AF6-213596pXZCC9S8g852g.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2AF6-213596pXZCC9S8g852g.png" title="pay function" alt="alt text" width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;pay&lt;/strong&gt; function allows spouses to use the money in the joint account to pay for various expenses like bills. The function checks if the amount that is requested is available in the joined account before deducting it and sending it.&lt;br&gt;
Once this is done, the function makes sure the total balance equals the joint account balance and the savings account balance.&lt;br&gt;
In the end, a &lt;em&gt;LogBalance&lt;/em&gt; event is emitted to update the user interface.&lt;/p&gt;

&lt;p&gt;To conclude, it is worth mentioning the &lt;em&gt;fallback&lt;/em&gt; function :&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%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AnfpTWvWC6ovUZk61cZCF2A.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%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AnfpTWvWC6ovUZk61cZCF2A.png" title="fallback function" alt="alt text" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any ether sent directly to the contract will be added to the joint account. Please note that the transaction will fail if around 42.000 gas is not provided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this article helped you understand the inner mechanics of a smart contract created to register marriages on the blockchain, to keep track of the marriage status, to manage a marital budget and to ease various processes involved in the bureaucracy of marriage.&lt;/p&gt;

&lt;p&gt;Beyond the practical side of such a contract, it is also envisioned as a demonstration of how far the blockchain can push the limits of our centralized society and open the gates of a decentralized world where we will all take back the power to make decisions for ourselves!&lt;/p&gt;

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

&lt;p&gt;You can find the website &lt;a href="https://www.marriageontheblock.com" rel="noopener noreferrer"&gt;here&lt;/a&gt;, the smart contract at &lt;a href="https://github.com/claudebarde/MarriageOnTheBlock/blob/master/contracts/MarriageCertificateCreator.sol" rel="noopener noreferrer"&gt;this address&lt;/a&gt; or check the &lt;a href="https://github.com/claudebarde/MarriageOnTheBlock" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>ethereum</category>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
