Try โ€‚โ€‰HackMD

Introducing Phage, Programmable Transaction Middleware by Shield3

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More โ†’

Phage is a rust based library that provides programmable middleware for Ethereum nodes. With Phage, developers can build:

  • Safer consumer wallets with anomaly detection, threat interception, and MFA flows
  • Enterprise trading wallets with protocol & sender specific rules, and pre-mempool alerting
  • Account abstraction tooling with dynamic transaction bundling
  • Optimized transaction routing with fee management & MEV protection

The middleware is designed to be modular, and extensible, enabling developers to program the Ethereum node to understand the intent of the user, and take the optimal action on their behalf. Using the middleware, developers can build applications that are more secure, more efficient, and more accessible.

In this article, we will explore the different types of modules that can be built using this middleware, including:

Why take a middleware approach

Developers currently have two primary options for defining and enforcing transaction rules: the user facing wallet/ application interface, and the smart contract. Both of these approaches have their own limitations, and are not well suited for many types of rules.

On the user facing wallet/ application interface, developers can define rules that are recommended to the user. This approach is well suited for rules that are simple, and that the user can easily understand. However, this approach is not well suited for rules that are complex, or that the user may not understand. For example, a user may not understand the implications of a transaction that is being sent to a smart contract, and may not be able to make an informed decision about whether or not to send the transaction. In addition, the user may not be able to understand the implications of a transaction that is being sent to a smart contract, and may not be able to make an informed decision about whether or not to send the transaction. When applications try to surface too many options and warnings to the user, this can lead to user fatigue, and can result in the user ignoring important warnings, especially when the user is responding to a high pressure situation.

On the smart contract layer, developers must define the set of permissable actions for interacting with their appliction, without overly restricting the composability and user experience of their protocol. This is a hard balance strike, and exposes users to a wide set of permissable, but sub-optimal transactions.

Historically, the node layer has been seen as a neutral component, only responsible for relaying valid transactions. However, the node layer is in a unique position to understand the intent of the user, and to take the optimal action on their behalf. The node layer is also in a unique position to understand the state of the network, and to optimize transactions based on the current state of the network. By taking a middleware approach, developers can build a layer of intelligence into the node that invisibly optimizes transactions and enforces rules on behalf of the user.

Phage Modules

Phage modules decode and analyze transactions received by the node, and take automated actions based on their policies. Phage modules can incorporate rich external datasets of on-chain and off-chain data, train and leverage machine learning models, and incorporate user defined policies. Policies are defined using the Banyan library, which is a rust based declarative language and policy engine for defining transaction rules based on a fork of the Cedar programming language developed by AWS.

Programming a Phage module

Suppose we want to build a simple module that enforces a multi-factor authentication policy for transactions over a specific limit. The module should intercept transactions, and send a push notification to the user's phone, asking them to approve the transaction. The user should then be able to approve the transaction from their phone, and the transaction should be signed and broadcasted to the network.

This module requires three components: a policy, a storage service to cache the signed transaction, and a notification service. The policy will define the conditions under which the user should be prompted to approve the transaction, and the notification service will send the push notification to the user's phone.

Defining the policy

Using the Cedar-Ethers library we can define the policy as follows:

    @name("WARN-NATIVE-ASSET-THRESHOLD")
    @advice("Warn when sending funds over X threshold")
    @notification("WEBHOOK-e03a0aa1")
    forbid (
      principal,
      action == Action::"EOATransaction",
      resource
    )
    when { principal has valueLimit && context.value.u256GreaterThan(principal.valueLimit) };

Defining the storage & notification services

The storage service will cache the signed transaction, and will be used to broadcast the transaction to the network. The notification service receives a webhook from the node, and sends a push notification to the user's phone. These services can be built using any language or framework, and can be hosted on any server. The notification service can also be built using a serverless framework, such as AWS Lambda.

The notification service sends a payload with the context of the policy violation, and a JWT signed payload that the user can use to broadcast the transaction to the network.

Execution

When the module receives a transaction, it decodes the transaction, executes the policy, and takes the appropriate action.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More โ†’

Additional module examples

Multi-Party Computation based transaction signing

We can adapt the above example to use a multi-party computation based signing scheme. In this case, the module is configured to trigger a signature when it detects a transaction below a specified value threshold, and to trigger an MFA notification when the value is above the threshold.

Defining the policies

Using the Cedar-Ethers library we can define the policy as follows:

    @name("WARN-NATIVE-ASSET-THRESHOLD")
    @advice("Warn when sending funds over X threshold")
    @notification("WEBHOOK-e03a0aa1")
    forbid (
      principal,
      action == Action::"EOATransaction",
      resource
    )
    when { principal has valueLimit && context.value.u256GreaterThan(principal.valueLimit) };

    @name("MPC-NATIVE-ASSET-THRESHOLD")
    @advice("MPC when sending funds under X threshold")
    @trigger("MPC")
    permit (
      principal,
      action == Action::"EOATransaction",
      resource
    )
    when { principal has valueLimit && context.value.u256LessThan(principal.valueLimit) };

Execution

The MPC service receives approved transactions and signs them before broadcasting to the network.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More โ†’

AI powered threat interception

A Phage module can be configured to predict the risk level of a transaction based on a machine learning model. The results of the model are passed into the policy engine, and the module can be configured to take different actions based on the risk level of the transaction. The model can be trained on a wide set of features, including the user's transaction normal history, a dataset of known malicious addresses, and a dataset of known malicious transaction patterns.

Defining the policy

Using the Cedar-Ethers library we can define the policy as follows:

    @name("ML-TRANSACTION-RISK")
    @advice("Block when transaction risk is high")
    @notification("WEBHOOK-e03a0aa1")
    forbid (
      principal,
      action,
      resource
    )
    when { context.riskConfidence.greaterThan(principal.riskLimit) };

Execution

The module receives a transaction, and passes it to the machine learning model. The model returns a risk level, and the module executes the policy based on the risk level.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More โ†’

Opt-in compliance management

A Phage module can be configured to detect transactions that present a compliance risk. By enforcing compliance rules on the node layer, developers do not have to build juristication specific compliance rules into their smart contracts, and can instead users can rely on the node layer to enforce compliance rules.

This module includes a compliance database which adds context to the decoded transaction before passing it to the policy engine.

Defining the policy

Using the Cedar-Ethers library we can define the policy as follows:

    @name("OFAC-COMPLIANCE-RISK")
    @advice("Block when transaction violates OFAC sanctions")
    @notification("WEBHOOK-e03a0aa1")
    forbid (
      principal,
      action,
      resource in Group::"OFAC"
    );

Execution

The module receives a transaction, decodes it, then queries the attached dataset to label the entities involved in the tranasaction.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More โ†’

Transaction fee optimization

A Phage module can be configured to optimize transaction fees based on the current state of the network and the priority of the transaction. The module can be configured to optimize for speed, or for cost, and can be configured to use a specific transaction broadcasting strategy.

This module can be programmed to query the predicted gas price from a third party service like GasHawk, and to use this information to optimize the transaction fee.

Defining the policy

In this example we can define a low priority transaction to include transactions executing multisig transaction, for example when running a payroll distribution. Using the Cedar-Ethers library we can define the policy as follows:

    @name("OPTIMIZE-FEE")
    @advice("Cache transaction to wait for optimal fee")
    @trigger("GAS-SERVICE")
    permit (
      principal,
      action: Action::Method::"executeTransaction",
      resource in Group::"SAFES"
    )
    when { context.predictedSavings(principal.maxWait).greaterThan(principal.savingsThreshold) };

Execution

The module receives a transaction, executes the policy engine, and if the policy is triggered caches the transaction to be broadcasted at a later time.

Sender based restrictions and alerting

A Phage module can be configured to configure permitted senders per application/ resouce group on a user's node, and route alerts to a unified channel. When used in combination with a network configuration to require all RPC calls from an institutional wallet to be sent to a node with the module installed, this module can be used to enforce sender based restrictions on a user's node and route alerting to a unified channel, such as a SOC.

Defining the policy

Using the Cedar-Ethers library we can define the policy as follows:

    @name("SENDER-MONITORING")
    @advice("Permit senders in group and receive alerts")
    @notification("WEBHOOK-e03a0aa1")
    forbid (
      principal,
      action,
      resource
    )
    unless { principal in resouce.senderGroup };

Execution

The module receives a transaction, decodes it, then queries the configured sender lists to label the entities involved in the tranasaction.

Transaction broadcasting strategy optimization

A Phage module can be configured to optimize transaction broadcasting strategy based on the MEV risk of a transaction. When a transaction has a high MEV risk, the module can trigger the transaction to be broadcast via a private transaction rather than via the mempool.

Defining a new policy

Using the Cedar-Ethers library we can define the policy as follows:

    @name("MEV-PRIVATE-TRANSACTION")
    @advice("Send via private transaction when MEV risk is high")
    @trigger("PRIVATE-TRANSACTION")
    forbid (
      principal,
      action,
      resource
    )
    when { context.mevRisk.greaterThan(principal.mevRiskLimit) };

Execution

The module receives a transaction, and passes it to the MEV risk assessment function. The model returns a risk level, and the module executes the policy based on the risk level.

Conclusion & Roadmap

Phage is a middleware library that enables developers to program Ethereum nodes to understand the intent of the user, and take the optimal action on their behalf. This approach takes the burden of understanding the implications of a transaction off of the user, enables smart contracts to remain open and composable, and enables developers to build applications that are more secure, more efficient, and more accessible.

Roadmap

Phage modules are currently available in a private beta. If you are interested in learning more about Phage, developing modules, or in participating in the beta, please reach out to us at isaac@shield3.com or @isaacpatka on telegram