Arbiter Release v0.3.0

Cover Image for Arbiter Release v0.3.0
Waylon Jepsen
Waylon Jepsen

Arbiter Release v0.3.0

Last week we released a new minor version of the Arbiter simulation and modeling framework, v0.3.0. The two months leading up to the release we were working hard on a whole host of new features all centered around improving the usability, modularity, and developer experience of Arbiter. The majority of these new features reside in the design of a modular interface over REVM. You can think of this interface as what an externally owned account(EOA) would interact with, and thus the interface used for modeling agents (that have an EOA). We cut down on lines of code, removed features we weren't using, and focused on simplifying the core logic and API we wanted to deliver. This release is a full rewrite of this interface, a step towards a better abstraction, and we are excited to share it with you!

Ecosystem Modularity

When we completed our first release, we compared it to the actual rust interface with the Ethereum JSON RPC through the state of the art ethers-rs rust ethereum library. We noticed a good developer experience with the ethers-rs interface, and we wanted to bring these properties to Arbiter. For example, the way one might make a call to a contract on main-net with ethers-rs if you have the rust contract bindings would look something like this:

// Create a new provider connected to the network let client = Arc::new(Provider::try_from("PROVIDER_URL".into_string())); // Create a new contract struct let address: Address = CONTRACT_ADDRESS.parse(); let abi: Abi = ContractBinding::CONTRACTNAME_ABI.clone(); let contract = Contract::new(address, client); // Call the contract function let value: u64 = contract.function_name().call().await;

Of course this is a simple example, the PROVIDER_URL must be a valid RPC URL and the bindings and address must also be valid for a deployed contract. But as you can see this is a very simple and familiar rust interface for interacting with a contract. Furthermore, if we could deliver the same API to users for agent design then the existing rust ethereum developers would have an API that they are already familiar with.

Middleware Trait

The ethers-rs ecosystem allows for modularity of abstractions around providers implemented as a trait called the middleware trait.

In Rust, traits define shared behavior that types can implement. They are similar to interfaces in other languages, allowing for polymorphism and abstraction. Types implement traits using the impl keyword, and once a type has implemented a trait, its methods can be called as if they were part of the type itself.

Trait bounds in Rust specify constraints on generic types, ensuring they implement particular traits. By setting these bounds, functions and structs can use methods guaranteed by those traits. Once the middleware trait is implemented and the trait bounds are satisfied, the middleware can be used in any context that expects a middleware in the ethers-rs ecosystem.

We decided to build a REVMMiddleware which satisfies the middleware trait bounds but rather than interacting over JSON RPC requests to a node, interacts with REVM in memory on the same machine.

#[async_trait::async_trait] impl Middleware for REVMMiddleware { type Provider = Connection; type Error = REVMMiddlewareError; type Inner = Self; // ... // the trait implementations // ... }

We create this Connection structure that serves as a provider for the middleware. This connection holds a variety of channels used communicate to a evm instance running in it's own thread encapsulated by the Environment.

The REVMMiddleware then communicates in memory to the REVM instance through the Connection provider and recieves the results of the call or transaction.

Following this architecture we are proud to deliver a new interface over REVM by implementing the middleware trait. For example here is some code that interacts with the REVM through the middleware.

But don't take our word for it, go and try it out yourself! We hope that this new interface will allow for more developers to build on top of REVM.

Developer Experience

Another big change we realize needed to be made was that in the first version of Arbiter, users had to contribute to the mono-repo directly in order to add new simulations. Now we re-architected the project to allow for users to create their own simulations in their own repositories and then import the Arbiter crate as a dependency. This allows for a much better developer experience and makes the project much more modular and easier to use. All you need to do to get started is run the following commands.

# install arbiter binary git clone https://github.com/primitivefinance/arbiter.git cargo install --path ./arbiter # create a new simulation arbiter init your-project-name cd your-project-name # generate contract bindings arbiter bind # run the example cargo run

Documentation

In efforts to make the new release more accessible we were sure to add extensive documentation to the new release. If you have the Arbiter repository cloned locally you can run the following command to build the documentation.

cargo doc --workspace --no-deps --open

Testing

We also brought the test coverage for the repository from 8% up to 58% with the new release. We hope to continue to improve this number as we continue to develop the project.

Looking Forward

The next steps for the Arbiter team are to design a number of simulations with the new middleware to understand how it can further be improved and what the limitations are. We are currently in the process of designing a number of simulations and are looking forward to sharing the results with the community. You can follow along the development of the most reecent simulation here. Furthermore, we are experimenting with the artemis framework for agent design.

We are happy to support any developers who are interested in building on top of the new release and if there are any questions please don't hesitate to reach out to us on telegram, we are very open to community feedback and if there is consensus on desired features we will be sure to implement them.

Special mention to the following repositories that are key dependencies to the new release. These pieces of software are what make the new release possible and we are very grateful for the work that has been done on them.

We have learned a lot working on this release and are excited to continue to iterate and improve!