Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ReserveGuard

ReserveGuard is an open-source Solidity library for building reserve-aware smart contracts on Monad.

It wraps Monad's MIP-4 Reserve Balance Introspection precompile at 0x1001 and provides simple primitives for detecting reserve violations, asserting healthy execution state, and placing explicit reserve checkpoints inside transaction flows.

Alpha Status

v0.1.0-alpha.1 is the current stable field-testing baseline. The V1 API is intentionally small so Monad developers can try it in real flows before the library expands.

If you test ReserveGuard in a wallet, router, vault, paymaster, batch executor, or EIP-7702 flow, use docs/field-testing.md to report what happened. The use-case matrix in docs/use-case-matrix.md tracks what has been observed and what still needs evidence.

Documentation

See the documentation map for stable V1, field testing, experimental work, dated observations, and historical release notes.

Install

This project is scaffolded for Monad Foundry.

forge build
forge test

If forge is not on your shell path yet, run:

source ~/.bashrc

or use the installed binary directly, for example:

~/.foundry/bin/forge test

Usage

import { ReserveGuard } from "./contracts/ReserveGuard.sol";

function execute() external {
    swap();
    ReserveGuard.checkpoint();

    borrow();
    ReserveGuard.checkpoint();

    stake();
}

With the base contract:

import { ReserveAware } from "./contracts/abstract/ReserveAware.sol";

contract Vault is ReserveAware {
    function withdraw() external reserveHealthy {
        // ...
    }
}

API

  • ReserveGuard.dipped() returns whether the current execution state has dipped into reserve.
  • ReserveGuard.assertHealthy() reverts with ReserveViolation() if reserve state is unhealthy.
  • ReserveGuard.checkpoint() is a semantic alias for assertHealthy() in V1.
  • ReserveAware exposes internal helpers and the reserveHealthy modifier.
  • ReserveProtected exposes a stricter reserveProtected modifier that checks before and after function execution.

V1 intentionally keeps the API small. Checkpoints are explicit fail-fast boundaries; they do not emit events, label checkpoints, or attempt recovery.

MIP-4 Notes

MIP-4 defines a reserve balance precompile at 0x1001 with:

function dippedIntoReserve() external returns (bool);

ReserveGuard preserves MIP-4 semantics and provides developer-friendly Solidity wrappers. A healthy checkpoint does not guarantee the transaction will remain healthy later; it only validates reserve state at the point where the check runs.

Examples

Developer-facing examples live in examples/.

Testnet experiments live in examples/testnet/, including EIP-7702 delegated drain/restore, tracing, agent-wallet, and recovery experiments. See docs/live-testnet.md for the live Monad testnet workflow, authorization commands, verified observations, and caveats.

The optional browser lab in app/ can be used to inspect the same testnet experiment patterns, but the Solidity library and examples are the primary integration path for Monad developers.

See docs/v1.md for the V1 release scope, non-goals, verification path, and testnet caveats. See docs/releases/v0.1.0-alpha.1.md for the alpha release notes.

Experimental post-V1 work lives under contracts/experimental/. See docs/experimental/reserve-trace.md for labeled observations and docs/experimental/reserve-recoverable.md for the application-defined recovery base contract.

Deploy to Monad Testnet

Set your environment variables in Bash:

export MONAD_RPC_URL="https://rpc.testnet.monad.xyz"
export PRIVATE_KEY="0x..."

Deploy the developer-facing examples:

forge script script/DeployExamples.s.sol:DeployExamples \
  --rpc-url "$MONAD_RPC_URL" \
  --private-key "$PRIVATE_KEY" \
  --broadcast

Deploy the live testnet experiment contracts:

forge script script/DeployTestnetExperiments.s.sol:DeployTestnetExperiments \
  --rpc-url "$MONAD_RPC_URL" \
  --private-key "$PRIVATE_KEY" \
  --broadcast

For where to get each value, how to map Foundry's Contract Address: output to env vars, post-deploy smoke tests, drain/restore checks, and the EIP-7702 reserve-dip workflow, see docs/live-testnet.md.

After deploying testnet experiments, the 7702 drain/restore flow can be repeated with:

bash scripts/run-7702-drain-restore.sh

The EIP-7702 delegated drain/restore experiment is intentionally documented as a live testnet workflow because local Monad Foundry validates delegated routing but may not reproduce the same reserve-dip semantics observed on testnet.

Security

  • Use disposable, testnet-only keys for deployment and EIP-7702 authorization experiments.
  • Never commit private keys, funded account credentials, or populated environment files.
  • Treat MIP-4 as a transaction-wide signal, not proof that address(this) caused the reserve violation.
  • A healthy checkpoint only describes the point where it runs; later execution can still dip.
  • ReserveTrace and ReserveRecoverable are experimental and are not part of the stable V1 API.

If a key is ever placed in a shared file, terminal transcript, issue, or chat, stop using that account and move any remaining test funds to a fresh testnet-only account.

License

ReserveGuard is available under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages