Grantline Docs
Reference

Action Plan

The current ActionPlan, TRANSFER, SWAP, parameter encoding, and EIP-712 signing shape.


The current contracts accept an ordered ActionPlan containing one or more typed actions. Two action types are supported: TRANSFER version 1 and SWAP version 1. This page describes the contract interface; use Normal execution for integration examples.

Solidity types

The current definitions are:

library ActionTypes {
    enum ActionType {
        TRANSFER,
        SWAP
    }

    enum SwapAdapterId {
        NONE,
        UNISWAP_V3
    }

    struct ActionPlan {
        uint256 mandateId;
        address agent;
        uint256 nonce;
        uint256 deadline;
        Action[] actions;
    }

    struct Action {
        ActionType actionType;
        uint8 version;
        bytes parameters;
    }

    struct TransferParameters {
        address asset;
        address recipient;
        uint256 amount;
    }

    struct SwapParameters {
        SwapAdapterId swapAdapterId;
        address tokenIn;
        uint256 amountIn;
        address tokenOut;
        uint256 minAmountOut;
        SwapHop[] hops;
    }

    struct SwapHop {
        address pool;
        address tokenIn;
        address tokenOut;
    }
}

ActionType.TRANSFER has enum value 0 and TRANSFER_VERSION is 1. ActionType.SWAP has enum value 1 and SWAP_VERSION is 1. The actions array must contain at least one action. The evaluator checks each action's type, version, and parameter bytes before it applies the Mandate rules.

Transfer parameters

TransferParameters is ABI-encoded with abi.encode, in this order:

(address asset, address recipient, uint256 amount)

The resulting parameters value is exactly 96 bytes for the current action. A zero asset means the Vault's native asset. A non-zero asset is treated as a token contract and is called through the Vault. recipient and amount must both be non-zero, and token amounts use the token's own raw base units.

A readable representation of a native transfer can look like this before ABI encoding:

{
  "mandateId": "1",
  "agent": "0xAgent",
  "nonce": "1",
  "deadline": "0",
  "actions": [
    {
      "actionType": "TRANSFER",
      "version": 1,
      "parameters": {
        "asset": "0x0000000000000000000000000000000000000000",
        "recipient": "0xRecipient",
        "amount": "1000000000000000000"
      }
    }
  ]
}

The JSON is explanatory only. The signed Solidity value contains actionType: 0 and the ABI-encoded bytes, not the readable nested object. deadline: 0 disables expiry; otherwise the evaluator rejects the plan after the Unix timestamp in deadline.

Swap parameters

SwapParameters is ABI-encoded with abi.encode. The evaluator validates the route through the configured adapter before accepting the action.

A readable representation of a swap can look like this before ABI encoding:

{
  "mandateId": "1",
  "agent": "0xAgent",
  "nonce": "2",
  "deadline": "1700000000",
  "actions": [
    {
      "actionType": "SWAP",
      "version": 1,
      "parameters": {
        "swapAdapterId": "UNISWAP_V3",
        "tokenIn": "0xTokenIn",
        "amountIn": "1000000000000000000",
        "tokenOut": "0xTokenOut",
        "minAmountOut": "950000000000000000",
        "hops": [
          {
            "pool": "0xPoolAddress",
            "tokenIn": "0xTokenIn",
            "tokenOut": "0xTokenOut"
          }
        ]
      }
    }
  ]
}

The JSON is explanatory only. swapAdapterId maps to the configured adapter through the Grantline facade. deadline on the ActionPlan must be non-zero for plans containing SWAP actions; the evaluator rejects a SWAP plan with deadline: 0 as INVALID_SWAP_PARAMETERS. minAmountOut sets the output floor; the executor reverts if the actual output is below it. Each hop describes one pool in the route, and hops chain together through consecutive tokenOut/tokenIn addresses.

The evaluator checks that the adapter is configured, calls validateSwap on the adapter, and accumulates the input amount for native-USD valuation. Route validation is adapter-specific: the Uniswap V3 adapter checks factory ownership, pool fees, token continuity, and deadline.

EIP-712 domain and types

The signature domain is:

name: Grantline
version: 1
chainId: <chain on which the evaluator is deployed>
verifyingContract: MandateEvaluator address from the deployment manifest

The domain type is:

EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)

The primary types are:

Action(uint8 actionType,uint8 version,bytes parameters)
SwapHop(address pool,address tokenIn,address tokenOut)
ActionPlan(uint256 mandateId,address agent,uint256 nonce,uint256 deadline,Action[] actions)

The evaluator hashes each action's parameter bytes, hashes the ordered action hashes as the actions field, hashes the complete ActionPlan, and combines that struct hash with the domain separator using the EIP-712 \x19\x01 prefix. Any change to the mandateId, agent, nonce, deadline, action order, version, or parameters changes the digest. Changes to the Mandate's current rules are read during evaluation and do not alter the signed digest.

The signature must be 65 bytes, use recovery identifier 27 or 28, use a low-s value, and recover to the agent stored on the Mandate. The verifying contract is the deployed MandateEvaluator, not the VaultExecutor or EscalationManager.

Current action surface

TRANSFER version 1 and SWAP version 1 are the current action surface. The executor runs actions in array order: native transfers, token transfers, or swaps. A failed action reverts the complete transaction. Other action types are not part of this contract version. A public SDK and API will provide higher-level integration surfaces when they are available.

See Normal execution for encoding and signing examples.

Last updated on

On this page