<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Protocol Review</title>
        <link>https://paragraph.com/@protocol-review</link>
        <description>A DAO that provides accessible, technical reviews of decentralized protocols.</description>
        <lastBuildDate>Mon, 06 Apr 2026 16:23:06 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Protocol Review</title>
            <url>https://storage.googleapis.com/papyrus_images/322beb95505fdf1f10488a46e123d9829ebbc6dfb12b0c897bdd74c757d30918.png</url>
            <link>https://paragraph.com/@protocol-review</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Sudoswap AMM]]></title>
            <link>https://paragraph.com/@protocol-review/sudoswap-amm</link>
            <guid>L7lbK7aIaWQs56b1q0uz</guid>
            <pubDate>Wed, 07 Sep 2022 15:48:59 GMT</pubDate>
            <description><![CDATA[Sudoswap is an efficient automated market maker (AMM) that supports exchanges between NFTs (ERC-721) and fungible tokens (ETH or ERC20). It facilitates the exchange of NFTs for ETH and tokens without locating a buyer or seller. This provides you with rapid liquidity as an NFT trader and makes trading NFTs similar to trading other tokens. Already, it has traded 23k ETH and 157k NFTs in volume, earning 620 ETH in fees for liquidity providers and 115 ETH in platform fees, with 25.5k unique walle...]]></description>
            <content:encoded><![CDATA[<p>Sudoswap is an efficient automated market maker (AMM) that supports exchanges between NFTs (ERC-721) and fungible tokens (ETH or ERC20). It facilitates the exchange of NFTs for ETH and tokens without locating a buyer or seller. This provides you with rapid liquidity as an NFT trader and makes trading NFTs similar to trading other tokens.</p><p>Already, it has traded 23k ETH and 157k NFTs in volume, earning 620 ETH in fees for liquidity providers and 115 ETH in platform fees, with 25.5k unique wallets trading. The governance token for the SudoAMM protocol $SUDO was also announced recently.</p><p>The SudoAMM model makes low-slippage swaps between NFTs and tokens available for traders. Liquidity providers can deploy a pool that will programmatically buy or sell an NFT at a given price (similar to limit orders), ultimately giving more power over the price ranges they fund.</p><p>In contrast to OpenSea, users can choose to sell NFTs into a pool at a specified price rather than waiting for a bid. With this, users may instantaneously sell their NFTs into a pool.</p><p>The protocol charges a 0.5% fee. Trading fees, which account for most of the fees generated, are sent to pool owners, providing liquidity for trading pairs. Overall, SudoAMM’s low fees come from exempting royalties on their trades, a controversial decision that has recently sparked debates — more on this later.</p><p>The most updated trading volume numbers and the details of the token allocation are linked in the resources section at the bottom of this post.</p><hr><p><strong>If you want to receive reviews of the latest protocols directly in your inbox, subscribe using the button below. By subscribing, you’ll enter a chance to win an edition of this post as a collectible!</strong></p><p>subscribe://</p><hr><h2 id="h-how-does-sudoamm-work" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How does SudoAMM work?</h2><p>The goal is to ensure that anyone can add liquidity to an NFT collection and earn trading fees. To do this, instead of an order book-based paradigm, SudoaMM uses liquidity pools - specifically, distinct liquidity pools. While separate pools increase gas expenses, the protocol has kept them low by writing gas-efficient code and innovating on the clones/proxy paradigm. New pools cost <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/sudoswap/status/1531313976654475264?s=20&amp;t=F_MGWhEi8O7KfB0LDdyDsw">180k gas</a>.</p><p>Those that supply NFTs and tokens (liquidity providers) can earn trading fees on their NFTs, which was never possible before. The creator of liquidity pools can set the price at which NFTs may be purchased or sold for ETH (or other tokens). Trading within the pool is possible as long as sufficient NFTs and ETH are in the pool. SudoAMM’s liquidity pool architecture provides dynamic provisioning using customizable bonding curves: Linear and Exponential Curves.</p><p>Each time someone trades within a pool with a linear curve, the pool&apos;s pricing will be shifted by a fixed amount of ETH (delta); and each time someone trades within a pool with an exponential curve, the pool&apos;s pricing will be multiplied by a percentage amount (delta).</p><h2 id="h-creator-royalties" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Creator Royalties</h2><p>Before diving into the technical analysis, we need to address the elephant in the room: SudoAMM does not implement creator royalties. This decision has been discussed at length from all different perspectives; we’ve linked resources at the bottom of this review if you’re interested in reading more about it.</p><p>Rather than joining that debate in this section, we want to explain why fees have been optional in the current marketplace landscape; and why it hasn’t been technically feasible to enforce royalty fees with the current standards.</p><h3 id="h-marketplaces-and-tokens" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Marketplaces and Tokens</h3><p>From a technical perspective, two main components make a marketplace — the marketplace contract and the assets traded in the said marketplace.</p><p>When an asset is traded, the token transfer is facilitated through the marketplace contract — this is why you usually need to send an approval transaction before you list an NFT; the approval transaction lets the marketplace transfer the NFT from your wallet when a trade is executed. Hence, all the funds and tokens exchanged are routed through the <em>marketplace</em> contract; the NFT does not control where funds go.</p><p>The NFT can only <em>specify</em> the amount and account to which royalties should be paid. The standard for specifying royalties is <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-2981">EIP-2981</a> — but again, the standard only defines a convention, which means some contracts specify them differently, increasing <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/0xkarmacoma/status/1559291918319865859">complexity in the marketplace contracts</a> as they try to figure out where to route royalties.</p><p>When a sale is completed, conventionally, the marketplace contract routes part of the sale to the royalty recipient specified on the NFT contract. Still, the marketplace can skip that step and send the full purchase amount to the seller — even if the NFT specified royalty information. This is why they cannot be enforced at the protocol level. This is what Sudoswap did; they skipped the royalties step and let the sellers keep the full sale amount.</p><hr><p><strong>If you’ve enjoyed this post so far, consider collecting it using the button below!</strong></p><p>collect://</p><hr><h2 id="h-technical-analysis" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Technical Analysis</h2><p>The protocol is broken down into separate components that define pairs, deploy new pairs and interact with them. In this section, we will go through the key contracts that comprise the protocol. We will break them down into four separate categories:</p><ul><li><p>Bonding curves — contracts that hold logic to calculate prices</p></li><li><p>Pairs — the contract that holds the tokens (also known as pools)</p></li><li><p>Factory — a contract used to deploy new token pairs</p></li><li><p>Router — a peripheral contract used to interact with token pairs</p></li></ul><h3 id="h-bonding-curves" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Bonding Curves</h3><p><strong>What is it?</strong></p><p>A bonding curve is a mathematical curve that defines the relationship between a given asset&apos;s price (NFT) and supply. Bonding curves are represented as smart contracts. Currently, the protocol supports two types of curves <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x5B6aC51d9B1CeDE0068a1B26533CAce807f883Ee#code">Linear</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x432f962D8209781da23fB37b6B59ee15dE7d9841">Exponential</a>.</p><p><strong>How does it accomplish this?</strong></p><p>The protocol implements the two bonding curves as contracts that more or less work as libraries. They take inputs from the pairs and return the new prices and other relevant information. The pairs then update their state to reflect new prices.</p><p>Each bonding curve implements the <code>ICurve</code> interface, which has four functions: <code>validateDelta</code>, <code>validateSpotPrice</code>, <code>getBuyInfo</code>, and <code>getSellInfo</code>.</p><p>For linear curves, function <code>validateDelta</code> and <code>validateSpotPrice</code> accept any delta value. However, in exponential curves, the delta must be greater than 1 for <code>validateDelta</code>, and the new spot price has to be larger than or equal to the minimum price of 1 gwei in <code>validateSpotPrice</code>. Both functions are called when initializing a new pool and the protocol; that way, the protocol can assume the values are correct and use them without verifying them.</p><p>Function <code>getBuyInfo</code> first verifies whether or not the user is buying one or more NFTs. Then, for linear curves, <code>getBuyInfo</code> performs an additive calculation that updates the price for each item bought with an additive operation. In exponential curves, <code>getBuyInfo</code> it performs a multiplicative operation to adjust the price for each item bought. With this, both curves update a new buy spot price upwards to avoid arbitraging LPs. The total cost of the items is then added to find the <code>inputValue</code> and the necessary protocol fees are applied.</p><p>Like <code>getBuyInfo</code> functions, <code>getSellInfo</code> functions also perform a check for one or more NFTs. Linear curves first compare the spot price to the total price decrease of all NFTs sold in the swap. If the <code>spotPrice</code> &lt; <code>totalPriceDecrease</code>, the new spot price is set to 0 to calculate the number of items that sell into the linear curve (until it reaches 0, the result is rounded up) and to avoid selling for a negative value. Otherwise, the new spot price would be the difference between the spot price and the total price change (delta * the number of items).</p><p>For exponential curves, <code>getSellInfo</code> first computes the inverse value of delta (1/delta). Then, it multiplies the spot price by the inverse delta (or divide by delta) to find the new spot price for each item sold, which is then put into a uint128 if the resulting value is less than 1 gwei. The total revenue of the items is then added up to find the <code>outputValue</code> and the necessary protocol fees are applied.</p><p>By summing up the <code>protocolFee</code>, starting <code>inputValue</code> or <code>outputValue</code>, and trade fee (for trade pools only), functions <code>getBuyInfo</code> and <code>getSellInfo</code> return the final <code>inputValue</code> or <code>outputValue</code>, <code>newSpotPrice</code>, <code>newDelta,</code> and <code>protocolFee</code>.</p><h3 id="h-pairs" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Pairs</h3><p><strong>What is it?</strong></p><p>The protocol’s base contract is <code>LSSVMPair.sol</code>, which can hold NFTs, tokens, or both and holds the core swap logic from NFTs to tokens. Each pool is a unique <code>LSSVMPair</code> contract owned by the account that created the pool and has unique settings such as the bonding curve type, pool type, delta, etc. After pool initialization, these pairings&apos; assets and price quotations are tracked.</p><p><strong>How does it accomplish this?</strong></p><p>Pairs are either <code>LSSVMPairEnumerable</code> or <code>LSSVMPairMissingEnumerable</code> depending if the NFT/Token pair supports the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-721#specification">enumerable ERC721 extension</a>. SudoAMM implements an ID set through <code>LSSVMPairMissingEnumerable</code> to allow easy access to NFT IDs in the pool if enumerable is not supported. Depending on the owner’s preferred token type, NFTs could be paired with either an ETH or ERC20.</p><p>Based on what the pair contains, an LSSVM pair can either be one of three types:</p><ol><li><p><code>TOKEN</code> - contains deposited tokens that will be swapped out for users’ NFTs. The pairs provide pricing for how much they will pay for any NFT in the collection.</p></li><li><p><code>NFT</code> - contains NFTs that will be swapped out for users’ tokens. These pairs produce a quote for how much it will sell for any NFT in its catalog.</p></li><li><p><code>TRADE</code> - contains NFTs and Tokens. Here, you can buy NFTs with tokens and sell NFTs for tokens (functionality of both <code>TOKEN</code> and <code>NFT</code> pair). The spread between buying and selling would be given to the pair owner as fees.</p></li></ol><p>The initialize function is invoked during pair deployment by the factory contract (more in the next section) to set the initial custom parameters of the new pool. The type of NFT collection, bonding curve, and pool type cannot be changed after the pool is deployed. With the <code>Ownable</code> library, pairs are only initialized once and are verified by ensuring the current owner is <code>address(0)</code>. A set pool fee of less than 90% is permitted solely for <code>TRADE</code> pools (&lt; 90% because the maximum protocol fee is 10%), while <code>TOKEN</code> and <code>NFT</code> pools have their pool fees set to 0.</p><p>Pairs compute the number of tokens or NFTs to send or receive by calling the assigned bonding curve contract (linear or exponential). Remember, the bonding curves are view-only contracts pairs utilize to establish the next trade’s pricing. Knowing this, the pair’s role is to continuously update the state of the pool’s bonding curve and carry out all input/output validations such as verifying the pool type and ensuring users are swapping more than 0 NFTs, and execute output checks that call the bonding curves for pricing information within its swap functions.</p><p>After pair deployment, the owner may adjust certain variables to alter the pair’s pricing and liquidity. The spot price, delta, and trade fee can be modified for <code>TRADE</code> pairs. For ETH pairs, the owner can withdraw their NFTs, ETH, or ERC20.</p><h3 id="h-factory" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Factory</h3><p><strong>What is it?</strong></p><p>The factory is a contract that deploys new pools and holds protocol-level configuration. The factory contract name is <code>LSSVMPairFactory</code>. Protocol pairs are deployed as clones; clones are smart contracts that hold storage but delegate logic to a separate smart contract.</p><p><strong>How does it accomplish this?</strong></p><p><strong><em>Deploying Pairs:</em></strong></p><p>The factory contract deploys pair clones through two functions,<code>createPairETH</code> and <code>createPairERC20</code>, each for the type of pair.</p><p>Each function validates the bonding curve type; validation is the same for both pairs. Since bonding curves are smart contracts, each type has a unique address. The factory stores a map of addresses to boolean values to represent if the bonding curve is allowed.</p><p>After validation, a new pair clone is deployed. The factory uses a custom version of the minimal proxy pattern. The standardized version of minimal proxies (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-1167">EIP-1167</a>) does not support immutable variables. Immutable variables and constants are held in the contract&apos;s <em>code</em> and not in storage — hence they’re much cheaper to store and access. The modified version allows proxies/clones to hold immutable variables by appending a few initialization parameters to the code; this optimization was pioneered by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/wighawag">wighawag</a> and called it <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/wighawag/clones-with-immutable-args">clone-with-immutable-args</a>; they explained:</p><blockquote><p>The immutable arguments are stored in the code region of the created proxy contract, and whenever the proxy is called, it reads the arguments into memory, and then appends them to the calldata of the delegate call to the implementation contract. The implementation contract can thus read the arguments straight from calldata.</p><p>By doing so, the gas cost of creating parametrizable clones is reduced, since there&apos;s no need to store the parameters in storage, which you need to do with <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-1167">EIP-1167</a>. The cost of using such clones is also reduced, since storage loads are replaced with calldata reading, which is far cheaper.</p></blockquote><p>The parameters stored in the code section are:</p><ul><li><p><code>ILSSVMPairFactoryLike factory</code></p></li><li><p><code>ICurve bondingCurve</code></p></li><li><p><code>IERC721 nft</code></p></li><li><p><code>uint8 poolType</code></p></li><li><p><code>ERC20 token</code> — only for ERC20 pairs</p></li></ul><p>In addition to more gas-efficient reads, the novel clone pattern saves five store operations for ERC20 pairs and four for ETH pairs.</p><p>After the pair is deployed, an initialization call is required to store and validate the initial parameters in the pair. The factory initializes the clones by calling <code>initialize</code> and passing in the <code>msg.sender</code> as the first parameter to be set as the pair&apos;s owner, as well as the asset-recipient, delta, fee, and spot price.</p><p>After the new pair is deployed and initialized, assets are transferred to the pair contract. For ERC-20 pairs, there are two additional parameters for transferring assets: <code>ERC20 token</code> and <code>uint256 initialTokenBalance</code>. These parameters specify the token and the amount that must be transferred to the pair contract at creation. For ETH pairs, a token doesn’t need to be specified since ETH is the base currency, and the amount used to initialize the pool is the value sent with the transaction, accessed through <code>msg.value</code>. Afterward, the NFTs specified for the pool are transferred from the owner to the pool. All assets are transferred using <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol">solmate’s SafeTransferLib.sol</a>.</p><p>After the assets are transferred, a <code>NewPair</code> event is emitted to signify a new pair has been deployed.</p><p><strong><em>Protocol Configuration and Ownership:</em></strong></p><p>The factory contract has an owner; the current owner is set to the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x4e2f98c96e2d595a83afa35888c4af58ac343e44">0xmons gnosis safe multisig</a> with a 3/5 threshold. The owner has the following capabilities:</p><ul><li><p>Updating protocol fees with a maximum of 10%</p></li><li><p>Updating the protocol fee recipient (currently set to the 0xmons multisig)</p></li><li><p>Withdrawing ETH and ERC20 fees from the factory; fees are sent to the protocol fee recipient</p></li><li><p>Add or remove bonding curves</p></li><li><p>Add or remove allowed routers</p></li><li><p>Set allowed contracts that a pair can call arbitrarily</p></li></ul><p>The owner functionality is implemented using <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol">OpenZeppelin’s Ownable.sol</a>; one critique of this pattern is that only one transaction is necessary to transfer ownership. A preferred pattern by some requires two — one to initialize the ownership transfer and the second to accept the ownership. With the said pattern, you always ensure that the new owner can submit transactions and it doesn’t lose ownership by accident; this was discussed at length on this <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/z0age/status/1549415879129047040">Twitter</a> thread.</p><h3 id="h-router" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Router</h3><p><strong>What is it?</strong></p><p>The Router contract consolidates token approvals into a single contract and facilitates swaps. The router contract name is <code>LSSVMRouter</code>.</p><p>Swaps work similarly to other DEXs; an input and output amount is specified, as well as a swap route and a deadline. The router addresses two types of swaps, Normal and Robust. A normal swap checks slippage (difference between desired input and output amounts) at the end of trade and reverts if exceeded. A robust swap checks slippage between each swap route and skips the swap if the slippage is exceeded.</p><p>The practical difference between both swap types is that sometimes robust swaps will be partially executed where normal swaps fully revert; completing part of the swap order provides a better user experience when trading in volatile pricing environments. More details on robust swaps are below.</p><p><strong>How does it accomplish this?</strong></p><p><strong><em>Token to NFT Swaps:</em></strong></p><p>Swapping ETH or ERC20 tokens for NFTs occurs within four functions:</p><ul><li><p><code>swapETHForAnyNFTs</code></p></li><li><p><code>swapETHForSpecificNFTs</code></p></li><li><p><code>swapERC20ForAnyNFTs</code></p></li><li><p><code>swapERC20ForSpecificNFTs</code></p></li></ul><p>Functions with the keyword “specific” permit users to specify which NFT IDs they want from each pair. Functions that contain the keyword “any” transfer an NFT ID determined by the pool.</p><p>Each of these functions checks if the swap meets the deadline set by the user through the <code>checkDeadline</code> modifier. If the swap is proposed at/after the assigned deadline, the swap will revert. If the swap is proposed before the deadline, these functions delegate swapping to their internal functions.</p><p>Internal functions <code>_swapETHForAnyNFTs</code> and <code>_swapETHForSpecificNFTs</code> query the pair&apos;s bonding curve and swap among the pairs specified. When querying, the pairs cannot directly “pull” ETH; so for ETH to NFT swaps, the router needs to calculate the price per swap with the function <code>getBuyNFTQuote</code> from <code>LSSVMPair.sol</code> to total the exact ETH amount it will send to the pool. This ultimately saves gas by eliminating the need to return any excess ETH.</p><p>Similarly, <code>_swapERC20ForAnyNFTs</code> and <code>_swapERC20ForSpecificNFTs</code> perform the same checks but don’t need to query the pair’s bonding curve with <code>getBuyNFTQuote</code>because when the Pair requires token transfers, it invokes the Router contract (it doesn’t transfer directly from the user’s wallet). The router contract checks if the caller is a Pair clone through the <code>LSSVMPairCloner</code> with the <code>isPair</code> function. If the pair is a clone, the router transfers tokens from the user’s wallet to the pair.</p><p><strong><em>NFT to NFT Swaps:</em></strong></p><p>NFT to NFT swaps occur within four functions:</p><ul><li><p><code>swapNFTsForAnyNFTsThroughETH</code></p></li><li><p><code>swapNFTsForSpecificNFTsThroughETH</code></p></li><li><p><code>swapNFTsForAnyNFTsThroughERC20</code></p></li><li><p><code>swapNFTsForSpecificNFTsThroughERC20</code></p></li></ul><p>Like Token to NFTs Swaps, NFT to NFT swaps also perform deadline checks. However, instead of calling one internal function, it calls two. The first internal function swaps an NFT to a token. Doing so ensures that it does an aggregate slippage check by setting the <code>minOutput</code>, which represents the minimum acceptable total excess ETH received, of the swap to 0 and returns the tokens to the <code>LSSVMRouter</code>. Afterward, a second internal function is called to swap tokens to NFTs and ultimately returns the total amount of ERC20 or ETH tokens received.</p><p><strong><em>Robust Swaps:</em></strong></p><p>For circumstances in which the price of your transaction might fluctuate rapidly between submission and execution, the <code>LSSVMRouter</code> resorts to robust swaps. The functions for robust swaps are:</p><ul><li><p><code>robustSwapETHForAnyNFTs</code></p></li><li><p><code>robustSwapETHForSpecificNFTs</code></p></li><li><p><code>robustSwapERC20ForAnyNFTs</code></p></li><li><p><code>robustSwapERC20ForSpecificNFTs</code></p></li></ul><p>A maximum per-swap cost is established to prevent an intermediate swap from executing if the specified price range is exceeded. Thus, users may request several swaps and have as many of them carried out as feasible. These robust functions are much like normal swaps, but with an added component of looping through swaps to ensure it meets the set <code>maxCost</code> standard with no errors before attempting.</p><p>The <code>robustSwapNFTsForToken</code> operation is alike the preceding robust swaps, except that it places value on the per-swap minimum output rather than the per-swap maximum cost. After checking for errors and verifying if it is at least equal to our <code>minOutput</code>, it proceeds to call the <code>swapNFTsForToken</code> function to perform the NFTs for Token swap.</p><p>Similar to NFT to NFT swaps, functions <code>robustSwapETHForSpecificNFTsAndNFTsToToken</code> and <code>robustSwapERC20ForSpecificNFTsAndNFTsToToken</code> also, perform two (robust) swaps in one transaction. The first swap involves buying specific NFTs with ETH or ERC20 tokens, and the second swap sells the NFTs for tokens in one transaction. All parameters are stored in a struct called <code>RobustPairNFTsFoTokenAndTokenforNFTsTrade</code> to prevent the “stack too deep” error.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>Sudoswap is a novel and ground-breaking protocol for the NFT ecosystem. NFT traders now have access to instant liquidity, which previously seemed difficult with NFTs. Bringing DeFi and NFT communities together improves the overall NFT market’s efficiency and liquidity, which onboards more users into the space.</p><h3 id="h-sources" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Sources</h3><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/sudoswap/lssvm">SudoAMM Source Code on Github</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.sudoswap.xyz/">Sudoswap Docs</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.sudoswap.xyz/sudo-distribution.html">Sudoswap’s SUDO Distribution</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ath.mirror.xyz/K-S_Mwhj7osTBqN-AOWbCmfNn9TZViEkzICCmK-oObM">Web3 Data Guide: Sudoswap</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.com/ilemi/sudoswap">Ilemi’s Dune Dashboard</a></p></li><li><p>Resources on royalties:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://goldenlight.mirror.xyz/VEkExWCvY0WUf0j33A7NJMdyZ65SLOhNskxORUdxCeU">Secondary Royalties in NFT: Inefficient, anti-market &amp; ethically suspect</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/kyric.eth/zyK1O9YVZvWz2ZEgUGr1i4_ZWPFEb3D9hDpfAtaOquE">👑 Cracking The Code of The NFT Flywheel, Pt. 2: The Royalty</a></p></li><li><p>punk6529’s threads: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/punk6529/status/1558920163386327042">first</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/punk6529/status/1563565644129660930">second</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zeneca33.substack.com/p/letter-30-creator-royalties-in-nfts?sd=pf">Letter 30: Creator Royalties in NFTs</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://0xfoobar.substack.com/p/on-royalties">On Royalties</a></p></li></ul></li></ul><hr><p><em>Protocol Review is excited to continue publishing accessible reviews for decentralized protocols. We believe in using our deep technical knowledge to distill protocols and increase their mainstream understanding.</em></p><p><em>To stay up to date with the latest reviews, subscribe to our Mirror publication and follow us on </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Protocol_Review"><em>Twitter</em></a><em>. If you have suggestions for protocols you’d like to see reviewed or are interested in writing for the PR, fill out this </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.google.com/forms/d/e/1FAIpQLScP_gNuZ4qz72wKpxq_P8pfffbGTfGwIrQf0TwtjCPFk0m6XA/viewform?vc=0&amp;c=0&amp;w=1&amp;flr=0"><em>form</em></a><em>.</em></p><p>Special thanks to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/willdphan">Will Phan</a> for the collaboration on this review.</p>]]></content:encoded>
            <author>protocol-review@newsletter.paragraph.com (Protocol Review)</author>
        </item>
        <item>
            <title><![CDATA[Bridging to Optimism]]></title>
            <link>https://paragraph.com/@protocol-review/bridging-to-optimism-2</link>
            <guid>U0f6KSojaY6KPqNfXFHv</guid>
            <pubDate>Mon, 06 Jun 2022 13:54:22 GMT</pubDate>
            <description><![CDATA[During times of high congestion, Ethereum can price out even its most enthusiastic users. We’ve seen this happen many times – quite recently with the Yuga Labs NFT drop, where some users paid thousands of dollars for a single transaction. There is an immediate need for scaling solutions for Ethereum that don’t compromise on its security guarantees. Optimism is one such solution. It makes transacting with Ethereum assets more affordable by constructing a separate “layer 2” blockchain where tra...]]></description>
            <content:encoded><![CDATA[<p>During times of high congestion, Ethereum can price out even its most enthusiastic users. We’ve seen this happen many times – quite recently with the Yuga Labs NFT drop, where some users paid thousands of dollars for a single transaction.</p><p>There is an immediate need for scaling solutions for Ethereum that don’t compromise on its security guarantees. Optimism is one such solution. It makes transacting with Ethereum assets more affordable by constructing a separate “layer 2” blockchain where transactions are cheaper, with exit guarantees back to Ethereum’s Layer 1. To get onto this L2 though, existing Ethereum users need to <em>bridge</em> their assets to Optimism.</p><h2 id="h-the-basics-of-bridging" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Basics of Bridging</h2><p>Optimism&apos;s execution environment is general purpose and practically the same as Ethereum; Optimism runs only a slight modification of the <em>Ethereum Virtual Machine</em>. This means that the same contract can be deployed to both networks, and we can expect them to work the same way.</p><p>Optimism contracts can communicate with Ethereum smart contracts (and vice versa)<em>,</em> via a <em>cross-domain messaging protocol</em>. We can use this protocol to build a “bridging contract” that facilitates asset transfers across the two networks – sending balance updates upon each deposit or withdrawal.</p><p>For example, the Uniswap $UNI token could be deployed to both Ethereum and Optimism, and users would be able to bridge these tokens back and forth. When a deposit to the bridge is made on Ethereum, the balance on the Optimism contract increases and grants more $UNI tokens to the user on that network.</p><p><em>Note: What’s extraordinary is that bridging in this way has the same security guarantees as an Ethereum transfer – as do all subsequent transfers on Optimism.</em></p><p>Messages that are sent across the two networks arrive asynchronously – unlike the instant calls we are familiar with from the EVM. Depending on whether we’re sending messages <em>to Optimism</em> (e.g. depositing), or <em>from Optimism</em> (e.g. withdrawing), the delay time will be very different. Messages sent to Optimism typically arrive in a few minutes, whereas messages that are sent from Optimism take at least a week. This seven-day delay is called a “challenge period” because during this time the transaction can be contested and overturned, given a valid <em>fault-proof</em>.</p><p>Despite the inherent delay in communication from Optimism to Ethereum, a few advanced bridging protocols have already solved withdrawal delays for common ERC20 tokens. Anyone who wants to use those protocols can get instant withdrawals for a small fee. This fee appears to be similar to what we experience in traditional withdrawals in the US – e.g. when withdrawing from Coinbase to a Chase account.</p><p><em>Note: The protocols that solve the withdrawal delay problem typically do so by composing with other stable financial protocols on Ethereum. They are an excellent example of the benefits of permissionless blockchain composability!</em></p><h2 id="h-the-standard-optimism-bridge" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Standard Optimism Bridge</h2><p>The Standard Optimism Bridge is a simple bridging protocol created by the Optimism team. While it doesn’t solve the withdrawal delay problem, it does give users a safe and standard way to bridge ETH and ERC20s between Optimism and Ethereum.</p><p>The protocol consists of two pertinent contracts:</p><ul><li><p>A bridge contract deployed to Ethereum, called <code>L1StandardBridge</code></p></li><li><p>A bridge contract deployed to Optimism, called <code>L2StandardBridge</code></p></li></ul><p>The two contracts know about each other; the <code>L1StandardBridge</code> on Ethereum stores an address for the <code>L2StandardBridge</code> deployment on Optimism, and the <code>L2StandardBridge</code> stores an address for the <code>L1StandardBridge</code>. The contracts use these addresses to transmit messages and validate received messages (since they only receive cross-domain messages from each other).</p><p>Additionally, the <code>L1StandardBridge</code> stores a balance of deposits for each ERC20 that has been deposited. It does this by mapping the L1 token address to the L2 token’s address, and mapping that to an integer that represents the deposit balance. The deposit amount is incremented when funds are sent to the bridge and subtracted when they are withdrawn.</p><h3 id="h-walkthrough-bridging-eth-to-optimism" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Walkthrough: Bridging ETH to Optimism</h3><p>The simplest way to bridge ETH to Optimism is just to send ETH directly to the standard bridge contract. In this case, the bridge’s <code>receive</code> method (which allows it to accept ETH directly), communicates with the L2 bridge contract through the <em>cross-domain messaging protocol</em>, instructing it to mint <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://optimistic.etherscan.io/token/0xdeaddeaddeaddeaddeaddeaddeaddeaddead0000">an ERC20 token that represents ETH on Optimism</a>.</p><p>Along the way, the protocol will need to produce a new block on Optimism, by queuing a transaction up on Optimism’s <em>Canonical Transaction Chain</em>. Here’s a technical breakdown of the process; the call-stack looks like this:</p><p><strong>L1 Call-Stack</strong></p><ul><li><p><code>receive()</code> - first, the contract handles the directly deposited ETH</p><ul><li><p><code>_initiateETHDeposit()</code> - it calls an internal function to initiate the deposit, specifying the transaction sender’s address as the beneficiary of the L2 funds.</p><ul><li><p><code>sendCrossDomainMessage()</code> - it uses a <em>cross-domain messaging protocol</em> to communicate with the L2 bridge contract. The method we want to call on the L2 contract is <code>finalizeDeposit()</code>.</p><ul><li><p>Since this makes use of a proxy contract, the first step will be to find the implementation and delegate the call.</p></li><li><p><code>getAddress()</code> - within the messaging protocol, an address is retrieved for the messenger’s implementation address, named <code>OVM_L1CrossDomainMessenger</code>.</p></li><li><p><code>sendMessage()</code> once the implementation is found, the call is delegated.</p><ul><li><p><code>resolve()</code> and <code>enqueue()</code> – finally, the transaction is enqueued onto the <code>CanonicalTransactionChain</code>.</p></li></ul></li></ul></li></ul></li></ul></li></ul><p><strong>L2 Call-Stack</strong></p><ul><li><p><code>relayMessage()</code> – Still within the <em>cross-domain messaging protocol</em>, but now running on the L2, a contract called <code>OVM_L2CrossDomainMessenger</code> relays the transaction to the relevant L2 contract: the <code>L2StandardBridge</code>. The message will be marked as successfully relayed after the L2 bridge’s method is called.</p><ul><li><p><code>finalizeDeposit()</code> – This method will check that the token is valid, and then attempt to mint the same amount that was deposited on the L1, to the transaction’s sender.</p></li></ul></li></ul><h3 id="h-depositing-erc20s" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Depositing ERC20s</h3><p>Besides sending ETH directly to the bridge contract, there are two other methods for depositing ERC20s to the bridge. The difference between them is just the ability to specify the recipient of the L2 token once the bridge transaction is complete. This difference is made clear by the function names:</p><ul><li><p><code>depositETH</code> - accepts deposits from an EOA (a non-contract account)</p></li><li><p><code>depositETHTo</code> - accepts deposits from an EOA or a contract, with the recipient specified</p></li><li><p><code>depositERC20</code> - transfers an ERC20 token from an EOA into the bridge contract</p></li><li><p><code>depositERC20To</code> - transfers an ERC20 token from an EOA or another contract into the bridge contract</p></li></ul><h3 id="h-walkthrough-withdrawing-from-optimism-to-ethereum" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Walkthrough: Withdrawing from Optimism to Ethereum</h3><p><strong>L2 Call-Stack</strong></p><ul><li><p><code>withdraw()</code> - the user calls on the <code>L2StandardBridge</code> contract, specifying the amount and the token (e.g. <code>0xdeaddeaddeaddeaddeaddeaddeaddeaddead0000</code> for Optimism’s Ether token)</p><ul><li><p><code>_burn()</code> - the L2 contract then attempts to burn the number of tokens specified. This will remove it from the sender’s balance, and decrease the total supply of those tokens on Optimism.</p></li><li><p>At this point, a <code>WithdrawalInitiated</code> event is emitted from the bridge contract. Also, the tokens are burned on Optimism, but nothing has happened yet on Ethereum.</p></li><li><p><code>sendMessage()</code> - The bridge now attempts to send a message to the L1 bridge, via the <em>cross-domain messaging protocol.</em></p><ul><li><p>The message to send is that <code>finalizeETHWithdrawal</code> or <code>finalizeERC20Withdrawal</code> should be called (depending on whether ETH or an ERC20 is being withdrawn), given arguments that include the equivalent amount of the token that was burned, and the address that should receive those tokens on Ethereum.</p></li><li><p>Specifically, it uses the <code>L2CrossDomainMessenger</code> contract to communicate this, invoking the method called <code>passMessageToL1</code>.</p></li></ul></li></ul></li></ul><p>At this point, the 7-day delay is invoked. The withdrawal transaction is received by the L1 bridging contract after one week. This window is called a “challenge period”, and it gives actors on the network time to challenge transactions with a <em>fault-proof</em>. Funds cannot exit from the Optimism network without this time delay.</p><p><em>Note: The length of this challenging period could technically actually be updated! Advocates for changing the challenge duration can argue their case via Github issues.</em></p><h2 id="h-transaction-fees" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Transaction Fees</h2><p>Transactions on Optimism are cheap but not free. Like on Ethereum, Optimism users have to pay gas for the amount of computation and storage they use.</p><h3 id="h-deposit-fees" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Deposit Fees</h3><p>A transaction that bridges Ethereum and Optimism will trigger a contract execution on both networks. The major cost of an Ethereum to Optimism deposit transaction comes from sending the transaction on Ethereum.</p><p>Optimism makes a particular concession on deposits – it gives away the first 1.92 million gas on L2 for free. Since the execution typically uses less gas than this, the L2 charge ends up being free. Users only pay for the L1 charge when bridging to Optimism.</p><p><em>Note: Optimism charges for gas limits higher than 1.92 million, to prevent denial of service attacks on the network. The amount is paid on Ethereum, at a rate of 1/32 of the Optimism computation beyond the free amount.</em></p><p><em>Both the 1.92 million gas concession and the 1/32 rate are updatable parameters – so they may change in the future.</em></p><h3 id="h-withdrawal-fees" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Withdrawal Fees</h3><p>A withdrawal from Optimism to Ethereum combines the L2 initialization transaction and the L1 finalization transaction. The L1 finalization transaction is usually more expensive than the L2 initialization transaction.</p><p>Since gas prices on Ethereum may be volatile and bridging transactions are asynchronous, it becomes Optimism’s responsibility to pay whatever the L1 gas price is after the sequencer has processed the transaction. If the L1 gas price spikes during the withdrawal, Optimism will need to pay a higher cost.</p><p><em>Note: Optimism currently does not have a mempool, which means there is no gas price auction when submitting transactions on Optimism. Instead, the network will reject low-fee transactions.</em></p><h1 id="h-conclusions" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusions</h1><p>We hope this has provided a thorough “walk across the Optimism bridge”, and that it provides some insight into how bridging in general works on Optimism. We are considering diving more deeply into other bridges that are more advanced, and comparing those to the standard bridge.</p><p>We expect a significant amount of ETH to move into the Optimism network, and that will need to happen across secure bridges such as these. Protocol Review is here to review!</p><hr><p>Protocol Review is excited to continue publishing accessible reviews for decentralized protocols. We believe in using our deep technical knowledge to distill protocols and increase their mainstream understanding. To stay up to date with the latest reviews or if you’re interested in writing for the publication follow us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Protocol_Review">Twitter</a>.</p><p><em>Thank you to everyone that made this post possible. </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/_avichalp_"><em>@avichalp</em></a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/zachobront">@zachobront</a> for your research and notes. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/julianjhutton">@julianjhutton</a> for your brand and design work.</p>]]></content:encoded>
            <author>protocol-review@newsletter.paragraph.com (Protocol Review)</author>
        </item>
        <item>
            <title><![CDATA[0xSplits]]></title>
            <link>https://paragraph.com/@protocol-review/0xsplits</link>
            <guid>bC8bxSKb6Nexg4T9AtPS</guid>
            <pubDate>Tue, 29 Mar 2022 11:59:58 GMT</pubDate>
            <description><![CDATA[Introduction0xSplits is a trustless protocol for splitting on-chain income. The protocol takes the form of a “hyperstructure”—a permissionless piece of infrastructure that distributes value to all users, operates at gas cost, and persists as long as the underlying blockchain reaches consensus. The smart contracts have been deployed to Ethereum mainnet and independently audited by Shipyard. The core components of the income-splitting mechanism are Splits and Recipients. A Split is a payable sm...]]></description>
            <content:encoded><![CDATA[<h2 id="h-introduction" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Introduction</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.0xsplits.xyz/">0xSplits</a> is a trustless protocol for splitting on-chain income. The protocol takes the form of a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://jacob.energy/hyperstructures.html">“hyperstructure”</a>—a permissionless piece of infrastructure that distributes value to all users, operates at gas cost, and persists as long as the underlying blockchain reaches consensus. The smart contracts have been deployed to Ethereum mainnet and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/0xSplits/splits-contracts/blob/main/audit/0xSplits_A-1.pdf">independently audited</a> by Shipyard.</p><p>The core components of the income-splitting mechanism are Splits and Recipients. A Split is a payable smart contract that receives ETH and ERC-20 tokens and proportionally allocates received funds to Recipients. A Recipient can be any address associated with an EOA (externally owned account) or smart contract. As of 3/27/2022, 580 ETH and 16 different ERC20 tokens have flowed through 267 Splits.</p><p>Splits can be designated as either Mutable or Immutable at creation, with Mutable Splits requiring a Controller address (the Controller of Immutable Splits is set to <code>0x0</code>, the Null Address). The Controller can modify a Mutable Split’s Recipients, percent allocations, and Distributor Fee after a Split has been created. The Controller can also transfer control to another address. While a Mutable Split can be set to immutable, an Immutable Split cannot be set to mutable. As of writing, 170 Immutable Splits and 97 Mutable Splits have been deployed, splitting income to 644 unique Recipients.</p><p>Splits are able to run at gas cost by relying on a third-party distributor to execute the transaction that updates Recipients’ withdrawable balances. In exchange for incurring gas costs, the distributor is rewarded with a Distributor Fee, a percentage of the total Split balance at the time of distribution. This fee can range anywhere from 0-10%. As of 3/27/22, the highest Distributor Fee earned is <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/tx/0x76a85b4263293dfa232be6849b281993e1ba6f173d2a4f32672f9683add32c89">0.22 ETH</a> for a 0.1% Split. As the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.0xsplits.xyz/getstarted/creating">protocol’s documentation</a> notes, a higher fee would likely lead to more frequent distributions, but the Recipients will be left splitting a smaller balance of funds.</p><p>We created a Dune dashboard with data analysis of existing Splits. Explore the data <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dune.xyz/ilemi/0xSplits">here</a>.</p><h2 id="h-interacting-with-the-protocol" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Interacting with the Protocol</h2><h3 id="h-creating-a-split" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Creating a Split</h3><p><code>createSplit</code> takes in four parameters:</p><ul><li><p>a list of Recipient addresses</p></li><li><p>a list of percent allocations corresponding to Recipients</p></li><li><p>a Distributor Fee, ranging from 0-10%</p></li><li><p>and a Controller address (if Mutable)</p></li></ul><p>Under the hood, <code>createSplit</code> deploys a minimal proxy clone that redirects function calls to <code>SplitWallet</code>; effectively, this Split proxy mimics the logic found in <code>SplitWallet</code> but costs minimal gas to deploy. As a result, every Split has a unique address that can receive funds and send them to <code>SplitMain</code>.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-1167">EIP-1167</a> defines a standard for a minimal proxy contract, but 0xSplits extends EIP-1167. Split proxies refrain from calling <code>DELEGATECALL</code> in their <code>receive</code> function to avoid delegating a function call to <code>SplitWallet</code>. Instead, the <code>receive</code> function emits a <code>ReceiveEth</code> event, with parameters of the Split proxy address and the amount of ETH received. This modification allows proxies to accept ETH sent by <code>send</code> and <code>transfer</code>. Both of these functions only forward 2300 gas, which would not be enough to cover a <code>DELEGATECALL</code> to <code>SplitWallet</code>. Accepting ETH sent with <code>send</code> and <code>transfer</code> improves the composability of Splits since some accounts or smart contracts may send funds using these hard-capped functions. While this non-standard proxy pattern offers more flexibility for sending funds to Splits, this modification prevents Etherscan from verifying Split proxy contracts.</p><p>The technical architecture separating <code>SplitMain</code> and <code>SplitWallet</code> proxies allows balances to be stored at the account level. Since account balances are stored on <code>SplitMain</code> and updated once a Split balance is distributed, Recipients can withdraw funds received from multiple Splits in one transaction.</p><h3 id="h-distributing-split-balances" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Distributing Split Balances</h3><p>Third parties can call <code>distributeETH</code> and <code>distributeERC20</code> to distribute Split balances to Recipients in exchange for a percentage of the total balance, defined as the Distributor Fee. Each ERC20 token requires a separate transaction call to <code>distributeERC20</code>.</p><p>The protocol ensures that distributors cannot alter Recipient addresses or their percentage shares by storing a hash of the Recipients, percent allocations, and Distributor Fee when a Split is first created. When either <code>distributeETH</code> or <code>distributeERC20</code> is called, a similar hash is created with the function’s parameters. This hash must match the original hash stored for a particular Split.</p><h3 id="h-withdrawing-account-balance" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Withdrawing Account Balance</h3><p>ETH and ERC20 token balances can be withdrawn in one transaction. Balances are stored at the account level in SplitMain, so Recipients can withdraw funds from multiple Splits once they have been distributed. <code>withdraw</code> takes in the Recipient address whose balances are being withdrawn as a parameter, meaning that anyone can withdraw funds on behalf of another account. Although the user interface currently only allows accounts to withdraw their own balances, users can <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.0xsplits.xyz/getstarted/withdraw">manually withdraw for another account</a> on Etherscan today. The 0xSplits team is in the process of adding delegated withdrawals to the user interface.</p><h2 id="h-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Conclusion</h2><p>0xSplits is a powerful and intuitive form of public infrastructure. The protocol encourages communities to create novel income streams and distribute them efficiently without worrying about additional overhead costs. At the same time, third parties can profit from arbitrage by distributing Splits with fees that outweigh transaction costs.</p><p>The full composability of Splits also engenders positive feedback as Splits can flush funds to other Splits and smart contracts. As of writing, <code>donations.0xsplits.eth</code>, the donations Split created by the team, is receiving income from 96 upstream Splits. Users should be cautious of sending funds to Mutable Splits that can be altered at any time, though the user interface provides sufficient warning on Mutable Split pages.</p><p><em>Thanks to everyone that helped get this review completed. </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/julianjhutton"><em>Julian</em></a><em> for the illustration, the 0xSplits team, and </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/andrewhong5297"><em>Andrew</em></a><em> for the dashboard.</em></p>]]></content:encoded>
            <author>protocol-review@newsletter.paragraph.com (Protocol Review)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/67f6c66056017fec075a602ce38262e540fd1a936974cc418e955cb23dd075e6.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Lens Protocol 🌿]]></title>
            <link>https://paragraph.com/@protocol-review/lens-protocol</link>
            <guid>USDUIAOKlWbaILfsRv4j</guid>
            <pubDate>Wed, 23 Feb 2022 18:06:36 GMT</pubDate>
            <description><![CDATA[Lens is a decentralized social graph protocol created by the AAVE team. The purpose of the protocol is to empower creators to own the links in the social graph that connects them with their community. Lens allows accounts to create and follow profiles, publish and collect posts, and much more, focusing on the economics of social interactions. The protocol is EVM compatible and is still in development (see Github). A version of it has been deployed to the Polygon Mumbai testnet. Nomenclature:A...]]></description>
            <content:encoded><![CDATA[<p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.lens.dev/docs/overview">Lens</a> is a decentralized social graph protocol created by the AAVE team. The purpose of the protocol is to empower creators to own the links in the social graph that connects them with their community. Lens allows accounts to create and follow profiles, publish and collect posts, and much more, focusing on the economics of social interactions.</p><p>The protocol is <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/evm/">EVM</a> compatible and is still in development (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/aave/lens-protocol">see Github</a>). A version of it has been deployed to the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.lens.dev/docs/testnet-addresses">Polygon Mumbai testnet</a>.</p><p><em>Nomenclature:</em></p><ul><li><p><em>Account refers to an </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/accounts/#types-of-account"><em>Ethereum account.</em></a><em> It could be an EOA or a Smart Contract.</em></p></li><li><p><em>NFTs refer to ERC-721 Non-Fungible Token Standard</em></p></li></ul><h2 id="h-lens-hub" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Lens Hub</strong></h2><p>Most interactions happen through the Lens Hub — a contract that implements profiles and publication interactions. Each profile and publication is an NFT created through this contract. Below is a list of interactions supported by the protocol:</p><ul><li><p>Create profiles</p></li><li><p>Follow profiles</p></li><li><p>Create posts</p></li><li><p>Collect posts</p></li><li><p>Comment on posts</p></li><li><p>Mirror posts (reposting)</p></li></ul><p>The Lens Hub keeps track of interactions through a mix of storage on the Lens Hub contract and callbacks that mint NFTs or provide custom logic through modules.</p><h3 id="h-profiles" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Profiles</strong></h3><p>Accounts can create profiles with a profile handle name, a profile image, a Follow NFT URI, and a <em>Follow module</em>. After creating a profile, a Lens Hub NFT is minted to the account that controls the profile.</p><p>The protocol uses its own profile name handling and restricts profile creation to an allowed list of accounts. The reason for this restriction is that the low fee environment of Polygon could lead to an excessive amount of profile name squatting. The protocol governance maintains the list of allowed profile creators. See the <strong>Security and Ownership</strong> section for more details on governance.</p><p>The Follow NFT URI is a content URI that is stored in the Lens Hub contract.</p><p>Currently, the profile image is just a URL. An improvement could be to allow profiles to have image modules. Image modules could delegate profile logic to NFT contracts.</p><h3 id="h-following" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Following</strong></h3><p>Following a profile consists of two main mechanisms: Follow NFTs and Follow modules.</p><p><strong>Follow NFT</strong></p><p>Follow NFTs are minted to follower accounts after following a profile. This means that following a profile comes with all the financial functionality and interoperability of NFTs. Some benefits could be airdrops, token gated content, or simply belonging to a cohort of accounts that hold a specific piece of digital art.</p><p>Each profile gets its own Follow NFT contract. If a profile does not have any followers, the first follow transaction deploys the Follow NFT contract. Since the follower is initializing the Follow NFT contract deployment, the protocol decides the name and symbol parameters for the Follow NFT. The name is set to the profile handle name with the suffix <code>-Follower</code> appended, and the symbol is the first 4 bytes of the handle name with the suffix <code>-Fl</code> appended.</p><p>The Follow NFT content function (<code>tokenURI</code>) calls back into the Lens Hub contract and returns the Follow NFT URI profiles specified when creating the profile.</p><p>An improvement would be to allow accounts to set up their own Follow NFT contract when setting up their profile. With this approach, the profile decides their name and symbol, and the first follower does not have to pay for the gas of deploying the Follow NFT.</p><p><strong>Follow Module</strong></p><p>Follow modules are contracts that specify the rules for new followers. The rules determine whether your account can follow a specific profile. There are a few different types of following modules:</p><ul><li><p>Permissioned — only accounts that you approved can follow you.</p></li><li><p>Fee — all accounts can follow you, but they need to pay a fee amount in the currency of your choice (ERC20).</p></li></ul><p>Currently, the <code>FeeFollowModule</code> implementation takes a percentage of the fee and sends it to a treasury.</p><p>Taking a modular approach to the following feature can be explored widely. A few ideas for new following modules are:</p><ul><li><p>NFT Follow Module — only accounts that hold specific NFTs can follow you.</p></li><li><p>Follow Back — only accounts that you follow can follow you.</p></li></ul><p>Creating profiles and publishing is a restricted feature, but all accounts can follow profiles as long as they satisfy the Follow module conditions.</p><h3 id="h-publishing" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Publishing</strong></h3><p>Publishing refers to creating posts and their interactions (collecting, comments, and mirrors). Only profiles can create posts, comments, and mirrors. However, similarly to following, collecting posts is open to all accounts.</p><p>Posts are created and stored on the Lens Hub by providing a content reference as well as a <em>Reference</em> and <em>Collect</em> module:</p><ul><li><p>A content reference is a string URL that points to content hosted outside the protocol.</p></li><li><p>A <em>Reference module</em> is a contract that determines the rules for commenting and mirroring the publication.</p></li><li><p>A <em>Collect</em> <em>module</em> is a contract that determines the rules for collecting the post.</p></li></ul><p>Collecting and commenting are subject to <em>Reference</em> and <em>Collect</em> <em>module</em> rules, while Mirroring is only subject to the <em>Reference</em> <em>module</em> rules.</p><p><strong>Collecting</strong></p><p>Collecting a post, mints an NFT with a reference to the original post. The Collect NFT stores the profile and post IDs used later to retrieve the post content.</p><p><strong>Commenting</strong></p><p>Commenting on posts mints an NFT with a reference to the original post and an additional content reference that holds the comment&apos;s content.</p><p><strong>Mirroring</strong></p><p>A Mirror refers to a “repost” of content. When you Mirror a post, the original post’s profile and publication ID are stored as a new post. No content references are stored since the Mirror can point to the original post for content.</p><h3 id="h-signatures" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Signatures</h3><p>A good design choice has been to allow publishing with signatures using a meta transaction approach. Transactions using signatures are supported for posting, commenting, mirroring, burning, and following.</p><p>This means that the end-user can interact with the protocol without spending any gas as long as someone else is willing to submit the transaction for you. This pattern is used in <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-2612">EIP-2612</a>, which describes a standard for granting ERC20 token approvals with signatures. A similar design has been used by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/">Mirror</a> by using Ethereum wallet signatures to publish content to Arweave.</p><h3 id="h-security-and-ownership" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Security and Ownership</strong></h3><p><strong>Dispatchers</strong></p><p>Profiles can specify a “dispatcher.” A dispatcher is an account that can act on behalf of a profile as a form of delegation or sharing profile access. Dispatchers can update profile information, post, comment, and mirror. Only the profile owner can update dispatchers.</p><p>Profiles can only specify a single dispatcher. However, a dispatcher could be a contract that allows multiple accounts to submit transactions, effectively allowing multiple accounts to control a single profile.</p><p><strong>Governance</strong></p><p>The Lens Protocol has a governance module currently in control of a multisig that has <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.lens.dev/docs/multisig-governance">special privileges</a>.</p><p><strong>Admin</strong></p><p>The governance role can update an “emergency admin” role. The emergency admin can update the state of the protocol. The states are:</p><ul><li><p>Paused — creating profiles and publishing (posts, comments, mirrors) is paused.</p></li><li><p>Unpaused — everything is unpaused.</p></li><li><p>PublishingPaused — creating posts, comments, and mirrors are paused.</p></li></ul><h2 id="h-closing-thoughts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Closing Thoughts</h2><p>The Lens protocol lays a foundational infrastructure to create connections between creators and their communities through on-chain interactions. The use of ERC-721 tokens gives users open access to their social graphs without any intermediaries. The Lens protocol is the beginning of social media moving away from old extractive models and letting creators own their social graphs.</p><hr><p>Protocol Review is excited to continue publishing accessible reviews for decentralized protocols. We believe in using our deep technical knowledge to distill protocols and increase their mainstream understanding. To stay up to date with the latest reviews or if you’re interested in writing for the publication follow us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Protocol_Review">Twitter</a> and join <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.gg/y5dPac9rjJ">Discord</a>.</p><p><em>Thanks to everyone that helped get this review completed. </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/julianjhutton"><em>Julian</em></a><em> for the illustration. Julie, Graeme, Denis, Lauren, and</em> Davidbrai for reading and editing the drafts.</p>]]></content:encoded>
            <author>protocol-review@newsletter.paragraph.com (Protocol Review)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/c4e7b606054fc770f52a9c32bd57f774de471b5930f6306f7b67a1cceea4864f.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Foundation Collections]]></title>
            <link>https://paragraph.com/@protocol-review/foundation-collections</link>
            <guid>rcFl1UCfR5I3yq2Qmnig</guid>
            <pubDate>Tue, 07 Dec 2021 17:39:20 GMT</pubDate>
            <description><![CDATA[NFT marketplace Foundation recently launched Collections — a way for artists to mint groups of NFTs on their own smart contracts. Collections allow artists to express a thematic relation among a group of their NFTs (just as a musician would for an album) and to describe the collection using the NFT&apos;s metadata. Collections also allow Foundation to aggregate and present data about a collection for potential buyers — such as its total sales, limits on the collection size, and floor price. E...]]></description>
            <content:encoded><![CDATA[<p>NFT marketplace <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/">Foundation</a> recently <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/withFND/status/1465727613297512456">launched <em>Collections</em></a> — a way for artists to mint groups of NFTs on their own smart contracts.</p><p>Collections allow artists to express a thematic relation among a group of their NFTs (just as a musician would for an album) and to describe the collection using the NFT&apos;s <em>metadata</em>. Collections also allow Foundation to aggregate and present data about a collection for potential buyers — such as its total sales, limits on the collection size, and floor price.</p><p>Each collection is described by a name, symbol, description, and an optional limit on the collection size.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/480a91c77144ffe909d2d2dd1804a314d7293daa9f99aaeb63cd1c803b4ad8a1.png" alt="An example collection by Jen Stark that has a unique namespace (Cosmos), a description of the collection, and information important for collectors, such as the collection size (60 NFTs), the other collectors, and the floor price. Although featured in Foundation&apos;s announcement tweet, this particular collection does not use Foundation&apos;s Collections contract — instead, it uses Manifold&apos;s Creator Core contracts, which provides similar functionality." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">An example collection by Jen Stark that has a unique namespace (Cosmos), a description of the collection, and information important for collectors, such as the collection size (60 NFTs), the other collectors, and the floor price. Although featured in Foundation&apos;s announcement tweet, this particular collection does not use Foundation&apos;s Collections contract — instead, it uses Manifold&apos;s Creator Core contracts, which provides similar functionality.</figcaption></figure><p>Foundation&apos;s creators understood the implications of the feature quickly, as 228 artists deployed a collection within 24 hours (over 450 deployments at time of writing) — despite paying an Ethereum transaction fee to do so.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/saturnial/status/1466198872875667460?s=20">https://twitter.com/saturnial/status/1466198872875667460?s=20</a></p><p>Previously, all of Foundation&apos;s artists minted NFTs on a single shared contract deployed by the platform. Although this made it cheaper to mint, it also meant that all artists were represented under the Foundation brand (instead of their own) on third-party marketplaces like OpenSea.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f417f9c632af7e59bdc0edd3da895ce1536c8b91165c2ea179070fd95db27ded.png" alt="Previously, all 100k NFTs minted on Foundation sat in a single collection called Foundation — with the symbol FND. This prevented artists from presenting under their own brand on marketplaces like OpenSea." blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Previously, all 100k NFTs minted on Foundation sat in a single collection called Foundation — with the symbol FND. This prevented artists from presenting under their own brand on marketplaces like OpenSea.</figcaption></figure><p>In our technical review, we explain how Collections are cheap to deploy, what the ownership and trust properties are, and generally dissect the engineering decisions that went into the most relevant features of the contracts.</p><h2 id="h-efficient-deploys-the-foundation-collection-factory" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Efficient Deploys: The Foundation Collection Factory</h2><p>Collections are deployed via the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x3b612a5b49e025a6e4ba4ee4fb1ef46d13588059#code">Foundation Collection Factory</a>. Deploying a Collection costs around 168k in Ethereum gas, which is very cheap — enabled by using OpenZeppelin&apos;s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.openzeppelin.com/contracts/4.x/api/proxy#Clones"><em>Clones</em></a> library, which implements the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-1167">EIP-1167 standard</a>. Foundation also used this pattern in their <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x1EF0159071b2A5898024cef4b4f78C171b7f48a8#code">Splits</a> feature.</p><p>The goal of the standard is to deploy a minimal amount of code to Ethereum for any functionality that is intended to be used by many contracts. It achieves this by separating the contract&apos;s storage from its functionality.</p><p>The state is deployed many times as separate, minimal, identical contracts (hence called a &quot;clone&quot;), and the large logic contract is only deployed once. The clones simply delegate transaction calls to the logic contract, which can modify the clone&apos;s state. This delegation pattern is known as a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.openzeppelin.com/proxy-patterns/">proxy pattern</a>.</p><p>As a result, artists on Foundation only pay for deploying a small clone that holds information about the collection (including its name and symbol) but that has the full functionality of a collection (such as minting and transferring).</p><p>A drawback of using a factory is that it makes the deployment an <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/tx/0xf0755a0fa646f2386ace2f7b2c20d8bf9679ba5a279adaff82dc9bfb1e2c2ed0/advanced#internal">internal deploy call</a> from the factory, and so some platforms might interpret the &quot;creator&quot; as the factory&apos;s address rather than the user&apos;s wallet. We&apos;ve seen this happen on OpenSea before when using factories to deploy ERC721 contracts.</p><p>On the other hand, using a factory makes tracking collections easier (e.g. via a subgraph on The Graph Protocol), and it&apos;s easy enough to define the creator as the wallet where the transaction originated.</p><p>Additionally, an optimization could be to deploy the contract and perform the first mint in the same transaction; currently, two transactions are needed to get to the point where a token is minted.</p><p>Another thing to note: The minimal proxy standard should not be confused with &quot;upgradable&quot; proxies — the proxies deployed through the Foundation Collection Factory are <strong>not</strong> upgradable.</p><h2 id="h-enforced-rarity-limiting-the-number-of-tokens-per-collection" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Enforced Rarity: Limiting the Number of Tokens Per Collection</h2><p><em>Collections</em> provide an optional way for artists to guarantee rarity in their collections — by allowing them to set a limit to the number of tokens that can be minted.</p><p>Each collection has a field <em>maxTokenId</em>, which defaults to zero, but can be set to a positive integer by the owner. Since each token&apos;s ID is effective an index — starting from zero and increasing once per mint — this field is used to prevent a token from being minted if its ID will be greater than the intended limit.</p><h3 id="h-limits" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Limits</h3><p>If the <em>maxTokenId</em> is never set and remains at zero, the owner can mint an unlimited number of tokens to the collection. However, once set, it can only be modified to a value that is <em>lower than the current value.</em> In other words, once the artist has committed to a limit for the collection&apos;s size, the collection is guaranteed never to grow beyond that limit.</p><h2 id="h-royalties" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Royalties</h2><p>Each token can have its own royalty payment address defined by the owner when minting. Royalties are set to a fixed amount of 1000 basis points (10%). The collections contract implements the royalties system defined originally by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x44d6e8933f8271abcf253c72f9ed7e0e4c0323b3#code">Rarible</a>.</p><p>The royalties implementation differs from the NFT Royalty Standard defined by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-2981">EIP-2981</a>. Builders in the space will benefit if a large platform like Foundation implements the EIP royalty standard as it allows for easier interoperability. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.manifold.xyz/">Manifold</a> has recently written a meticulous library for marketplaces to aggregate all royalty implementations into a standard. Standardization reduces the need to use libraries that <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/manifoldxyz/royalty-registry-solidity/blob/main/contracts/RoyaltyEngineV1.sol#L85">aggregate many disparate strategies in a single function</a> as added optionality is error-prone.</p><h2 id="h-ownership-and-trust-assumptions" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Ownership and Trust Assumptions</h2><p>The collections factory and logic have roles that manage different privileges.</p><h3 id="h-factory-contract" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Factory Contract</strong></h3><p>The collections factory contract has a roles contract set to Foundation&apos;s treasury, which extends OpenZeppelin&apos;s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.openzeppelin.com/contracts/4.x/api/access">Access Control</a> implementation. The roles contract serves two purposes:</p><ul><li><p>It defines the admin role that has privileges such as updating the implementation of the collections contract, meaning it can update which &quot;logic&quot; gets deployed with the proxies</p></li><li><p>It defines the operator roles queried from the collections contract</p></li></ul><h3 id="h-collections-contract" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Collections Contract</strong></h3><p>The collection contract implements a standard ERC-721 with two roles. An owner role that is set to the user&apos;s wallet; and an operator role that is set to a role contract specified by the factory.</p><p>Owner capabilities:</p><ul><li><p>Set the maximum number of tokens that can be minted in the collection</p></li><li><p>Update the baseURL</p></li><li><p>Burn any tokens owned by the collection owner. Collectors cannot burn tokens.</p></li><li><p>Mint tokens with a combination of automatically approving a specified operator (auction house, marketplace, etc) and setting a royalties recipient</p></li></ul><p>Operator capabilities:</p><ul><li><p>Migrate tokens from one account to another with the original token owner&apos;s permission (using signatures)</p></li></ul><h2 id="h-final-thoughts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Final Thoughts</h2><p>Web3 is about ownership. Foundation has taken a necessary step towards giving creators more ownership over their work and image while making it as accessible as possible through opinionated product decisions and inexpensive deployments. We like the collections.</p><p><strong>References:</strong></p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x3b612a5b49e025a6e4ba4ee4fb1ef46d13588059#code">Factory Contract</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x331c421106619d4217d41c3e073b1e64f4974563#code">Implementation Contract</a></p></li></ul>]]></content:encoded>
            <author>protocol-review@newsletter.paragraph.com (Protocol Review)</author>
        </item>
    </channel>
</rss>