Skip to main content

Environments

Environments are the heart of a simulation. Each simulation has at least 1 environment, which simply said is a single chain instance. For now only Ethereum is supported, but plans for other EVM based chains are in the works.

Agents can retrieve information from an environment and perform actions in it. Each step in the simulator the agent is allowed to take actions on one or multiple chains depending on how the timing of the chains are configured (for now this isn't a concern since only Ethereum mainnet is supported).

An Environment has many components to it and has to be configured using both the configuration file and a Python class implementation.

Configuration

Each environment needs to have the following components as part of its configuration:

  • alias (required)
  • block (required)
  • chainId (required)
  • contracts (optional)
  • dependencies (optional)
  • engine (required)
  • metrics (optional)
  • settings (optional)
  • source (required)
  • tokens (optional)
  • blockchain (optional, if not present Ethereum is assumed)
  • network (optional, if not present regnet is assumed)

alias is a simple name to reference the environment by. This is used a primary key and will be used in other areas of the simulation to refer to this specific environment. TIP: Pick a name that is human readable.

block is the starting block from which the specific chain that has been specified using engine and chainID will be forked from the mainnet. If running a simulation with multiple environments you should make sure this aligns with the other environment blocks.

chainId helps specify which chain we want to use for this environment. The source of truth is this list from sourcify for EVM chains.

contracts more about contracts can be read here.

dependencies more about dependencies can be read here.

engine helps with identifying which chain the environment is running. For now only evm is supported, but in the future items like cosmos or solana could be added for example.

metrics more about metrics can be read here.

settings is a simple "key value" list that can help modularize environments. They can take anything as a value which will be passed into the environment class.

source is the location of the Python file that implements the EnvironmentInterface. Read more about sources here.

tokens more about tokens can be read here.

blockchain is the name of the blockchain you wish to simulate with. We currently support ethereum, arbitrum and avalanche, but we may add more L2 in the future.

network is the name of the blockchain network. Currently, we support mainnet and testnet. The goal is to be able to simulated in several networks. The only testnet we support is Sepolia for Ethereum.

An example of a configuration looks like this:

- alias: ethereum1
block: 16100000
chainId: '1'
contracts:
- abi: '[{"inputs": [], "stateMutability": "nonpayable", "type": "constructor"},
{"inputs": [{"internalType": "uint256", "name": "_value", "type": "uint256"}],
"name": "increment", "outputs": [], "stateMutability": "nonpayable", "type":
"function"}, {"inputs": [], "name": "number", "outputs": [{"internalType": "uint256",
"name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"},
{"inputs": [], "name": "reset", "outputs": [], "stateMutability": "nonpayable",
"type": "function"}]'
alias: incrementer
installable:
bytecode: 608060405234801561001057600080fd5b50600080819055506101db806100276000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637cf5dab0146100465780638381f58a14610062578063d826f88f14610080575b600080fd5b610060600480360381019061005b91906100eb565b61008a565b005b61006a6100a1565b6040516100779190610127565b60405180910390f35b6100886100a7565b005b806000546100989190610171565b60008190555050565b60005481565b60008081905550565b600080fd5b6000819050919050565b6100c8816100b5565b81146100d357600080fd5b50565b6000813590506100e5816100bf565b92915050565b600060208284031215610101576101006100b0565b5b600061010f848285016100d6565b91505092915050565b610121816100b5565b82525050565b600060208201905061013c6000830184610118565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061017c826100b5565b9150610187836100b5565b925082820190508082111561019f5761019e610142565b5b9291505056fea264697066735822122072e7fdd0a3a63d596b9da980049bd6c53b405daff56912d3871ff9e9f4007e7664736f6c63430008120033
dependencies:
- settings:
uniswap_v3_usdc_pool: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
source: file://protocols/uniswap-v3/
- source: file://protocols/aave-v3/
engine: evm
metrics:
- alias: amazing_environment_metric
source: file://metrics/amazing_env_metric/
settings:
autoApprove: false
autoImpersonate: true
enableEvmLogging: true
source: file://environments/environment1/
tokens:
- address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
name: USDC
- address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
name: WETH

Class implementation

One of the required items for the environment is a Python file that implements the EnvironmentInterface. If you haven't done this before please read this first before continuing.

You can find an example of an environment that has implemented the EnvironmentInterface in the configuration template under environments/environment1/main.py (use simcli generate to get the template in a local directory).

✅ What to add to the Environment implementation:

  • Doing initial state changes before the simulation to the environment (both on-chain and off-chain).
  • Changing certain on chain paramaters after or before every step.
  • Calculating a value to store in the environment state (off chain), that can be used in next steps.
  • Calculating final state values that can be used for metrics.

❌ What not to add:

  • Performing actions on behalf of agents
  • Logging metrics inside the environment (use environment metrics)

Methods to implement

__init__(self, environment_helper: EnvironmentHelperInterface, metric_helper: MetricHelperInterface)
environment_initialization(self)
environment_pre_step(self)
environment_post_step(self)
environment_teardown(self)

Library file

The library file for the environment class supports a few extra parameters besides the standard ones, see a full example of a library file for an agent below:

name: "Super amazing environment"
version: "1.0.0"
type: "environment"
author: "Almanak Blockchain Labs"
description: ""
license: "MIT"

supported_chains:
- engine: 'evm'
chainId: '1' # Ethereum Mainnet
dependencies:
protocols:
- "library://almanak/protocols/aave-v3:1.0.0"
- engine: 'evm'
chainId: '17000' # Ethereum Holesky
dependencies:
protocols:
- "library://almanak/protocols/aave-v3:1.0.0"
settings:
uniswap_v3_usdc_pool: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"

As you can see the main part that we add is the supported_chains, which is simply an array of objects that you can use to configure dependencies and only allow the agent to work on certain chains because it has unique features to them.

  • engine is the Chain Engine as configured for the environment.
  • chainId is the chain id as configured for the environment.
  • dependencies allow you to set certain dependencies on an environment level, these have to be library items.
  • settings are like any other settings but can overwrite them on an environment level. Useful for contract addresses that are different per chain