Forks, Factories, and Upgradable MEM Functions

Forks, Factories, and Upgradable MEM Functions

January 18, 2024

It is now possible to manually or programmatically fork any MEM mainnet function, making it easy to duplicate MEM source code, set a new state, and push the function live on the network in a single http request. This feature makes the factory model possible with MEM and has useful synergy with upgradable functions (MIP-3). In this post, we’ll explain how to use these new MEM features to improve your development experience building web3 serverless functions.

Use cases

  • Fork with original state — duplicate an application built with MEM and keep the state in tact
  • Fork with clean state — duplicate the function but reset the state to blank
  • Fork with modified state — duplicate the function but mutate the state (e.g., changing global variables)
  • Fork to testnet — pull a mainnet function into a fork on testnet, allowing you to safely experiment

How fork works

Behind the scenes, forks are tracked in a MEM function that calls a new molecule — fork — with deterministicFetch(). The molecule pulls source code and state from Arweave, calls the MEM API to deploy a forked function, then logs the ID of the fork in the function factory state. This registry provides a public record of derivatives.

The factory model

A MEM function that can fork itself is a useful model for building applications with sharded state.

Let’s take the example of a content publishing backend. One approach could be to deploy a single master function to store an array of every user’s content body, metadata, author details, etc., but downloading and traversing for the exact piece of data needed within the state for each query could become unworkable at scale.

Factory model diagram

MEM forks enable the factory model and make it easy to programmatically spin up one function per user and store the map of { user, functionId } in a top-level registry function for rapid access to the right data at scale.

Synergy with MIP-3 (upgradable functions)

Last month we proposed and implemented MIP-3 — a feature to allow MEM functions to be upgraded by their deployer if originally marked upgradable.

The rationale behind this improvement is that it is a common web2 convenience to be able to push changes to code that has a single persistent ID. A persistent ID means that applications which depend on the function don’t need to actively upgrade to get the new version, making it simple for a developer to broadcast an update and not incur the need for all dependent apps to update.

The problem with this pattern in web2 is that there is often no transparency or ability for developers to go back in time and deploy a fork that reverses the process. Think about times where unexpected API deprecation suddenly puts a whole ecosystem out of business. One of web3’s major strengths is that once code is deployed it is guaranteed to be immutable and referenceable by a single ID.

We thought about these trade-offs when implementing upgradable and forkable functions, and worker to bypass the downsides while giving developers the convenience they’re used to in web2:

  1. MEM functions must be explicitly marked as upgradable at the time they are deployed. This makes the fact that the functionality could change a matter of public record
  2. Unlike typical web2 applications, every version of MEM function source code is stored permanently on Arweave. Any other developer is free to fork back to a previous iteration of state or source and deploy their own
  3. A record of upgrades is stored in a convenient MEM registry built specifically for MIP-3. Similarly, forks are stored in a MEM function registry (these features are native to the platform and implemented in pure MEM)

Coming soon

The first version of the MEM SDK is due for release soon and will ship with in-built support for .fork. Also watch out for named functions which abstract away function IDs to simple .mem addresses resolved by a MEM naming registry.

Follow along on X for more updates.