RSS Amplifier

Degen Code · Jun 9, 2026

Optimizing Smart Contracts With Autoresearch

0
Sign in to vote or save

BowTiedDevil · Degen Code

I’ve been using AutoResearch (AR) to improve smart contracts.

I don’t see AR discussed often enough, and I think it suffers from a branding problem.

The name suggests it is a tool for finding obscure info, digging into scientific papers, or summarizing dense source material. But it’s really much more practical.

At a high level, AR is a simple technique for performing a series of structured experiments, measuring the impact to some evaluation metric, and choosing to keep or discard those individual changes.

At the end of my Uniswap V4 series, I introduced a gnarly “virtual machine” command-based executor contract for handling swaps between multiple DEX and pool versions.

It was inspired by the Uniswap V4 Router design which used byte encoding of arbitrary commands across multiple contracts supported by the exchange.

Its complexity made it a real pain to build, test, and debug. So I got it working, ensured it satisfied my synthetic test cases, ran some live arbitrage to confirm it was functional, then moved on.

But there was a lot of potential left on the table!

At the end of last year, AI models got really good and CLI coding harnesses became very sophisticated. Suddenly I could dedicate a lot of idle computing resources to background refinement of techniques I had already started, like the VM executor.

Ultimately I want to build a flexible executor contract that supports command-based execution of atomic swaps across any mixture of Uniswap V2, V3, and V4 pools (and all forks).

Building the contract will be done through a series of AR refinements to a single executor smart contract using Vyper version 0.4.3.

Tests will be written using Ape Framework version 0.8.50.

The AI harness is Pi version 0.79.0 using the pi-autoresearch extension. The backend AI model is GLM-5.1.

It would be overwhelming to bring the full set of Uniswap versions in scope initially. So let’s start with something really simple: build a contract that can execute a chain of Uniswap V2 pool swaps, then do AR runs on it until we’ve optimized it and see what we get.

I’ve already created a set of fake contracts that I can use for simulating Uniswap V2 pools and their underlying ERC-20 tokens.

fake_erc20.vy

fake_weth.vy

fake_uniswap_v2_pair.vy

Ask the AI to write the initial contract:

Write a Vyper smart contract, command_executor.vy, to support executing encoded byte command streams at transaction time. The contract will support up to 255 unique 1 byte commands (0x00-0xFE) plus a 1 byte separator (0xFF).

All encoded commands shall be structured as concatenated bytes with fixed offsets:

[1 byte] - COMMAND
[X bytes][Y bytes][Z bytes] - arguments necessary for execution of the given function
[1 byte] - SEPARATOR

The contract will use immutable variables set at deployment time, starting with these:
OWNER, holding the deployer address
WETH_ADDR, holding the Wrapped Ether contract address

The contract shall not use durable storage. The contract may use transient storage using the transient keyword to pass data across call frames where needed.

Provide a fallback function __default__ which accepts zero-calldata Ether transfers but reject all other calls.

Create a single external function called execute_commands. Protect the function with a top-level assertion: msg.sender == self.OWNER.

Provide initial support for one command: CMD_V2_SWAP_EXPLICIT_AMOUNTS that performs a swap call at a given Uniswap V2 pool.

It generated this contract:

command_executor.vy

The AR extension comes with an autoresearch-create skill, so I load it and have this brief interaction:

I have the autoresearch skill loaded. What would you like me to optimize? I need to know:

1. Goal — What are we optimizing?
2. Command/Benchmark — How do we measure it?
3. Metric — What number are we trying to improve (and which direction)?
4. Constraints — Any hard rules (tests must pass, no new deps, etc.)?

Or if you’d like me to explore the codebase first to suggest an optimization target, I can do that too.

I respond:

I want to create an autoresearch task with an optimization target of minimizing total gas use of a transaction that captures profit from a synthetic arbitrage scenario through three Uniswap V2 pools (V2-V2-V2).

Build an Ape test that generates the profit scenario using @contracts/fake_erc20.vy, @contracts/fake_uniswap_v2_pair.vy, and @contracts/fake_weth.vy.

Build fake pools as pytest fixtures, initialize them using fake tokens, assign the tokens and mint pool reserves that result in a profit after fees. The test must assert that the transaction results in a positive gross WETH profit at the executor contract, but net WETH profit (considering gas fees) may be ignored.

The model considered this for a while, then added a new command to the contract to support ERC20 transfers between pools. I already know this is sub-optimal because V2 pairs support direct transfers between themselves, but that’s fine. The AR loop should be able to discover this!

The model then wrote an experiment log (log.jsonl), configuration (config.json), scripts for experiment measurement (measure.sh) and checking (checks.sh), and a prompt for the model (prompt.md).

Then it ran a baseline test for the starting V2-V2-V2 scenario: 202,464 gas.

Then I started the AR run using the extension command /autoresearch minimize V2-V2-V2 gas use.

It quickly started iterating over improvements and opened an experiment result overlay in the terminal showing results of its experiments:

It ultimately made 18 passes, reducing the gas use to 169,765 with a hyper-optimized contract that only includes one dedicated V2-V2-V2 function:

I want to highlight one nice optimization that AR found: Since Uniswap V2 performs the post-swap check against reserve values held in storage, you can transfer tokens to it before calling swap. So you can effectively transfer the intermediate amounts directly between pools by passing pool2’s address to the swap call at pool1. This reduces the number of ERC-20 transfers to the theoretical minimum, n_pools + 1.

But you’ll also noticed that is stripped the command stream mechanism and transient storage features completely! This makes sense because the feedback mechanism only tracked the gas use of a V2-V2-V2 chained swap, so it was correct to focus on that slice and ruthlessly cut anything not supportive of that goal. Hard-coding the swaps is absolutely the right call there, but there are more optimizations still on the table.

IMPORTANT LESSON: optimizations selected by the AR loop are downstream of the feedback mechanism.

Close that AR loop by running /autoresearch off, then start another with a new more specific goal: /autoresearch Optimize V2-V2-V2 arbitrage without relying on an initial balance held by the execution contract.

Read the original on degencode.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.