Protocol Modules

Protocol modules are the bridge between NMT's permission system and external DeFi protocols. Each module knows how to interact with one specific protocol.

Module Architecture

All modules inherit from BaseModule.sol, which provides:

  • Permission checking (queries PermissionsManager)
  • Safe call utilities (executes transactions through the user's Safe)
  • Common safety checks
BaseModule (shared logic)
    |
    +-- UniswapV3Module
    +-- UniswapV2Module
    +-- AaveModule
    +-- MorphoModule
    +-- YearnModule
    +-- AerodromeModule
    +-- RelayModule

External modules (not in this repo):
    +-- CowModule         (MEV-protected swaps via PRESIGN)
    +-- KrystalModule     (automated LP vaults, ERC-4626)

Module Details

UniswapV3Module

Protocol: Uniswap V3 (concentrated liquidity) Operations: Mint position, burn position, collect fees, increase/decrease liquidity

This is the most complex module because Uniswap V3 positions are NFTs with specific price ranges (tick ranges). The module handles:

  • Creating new concentrated liquidity positions with specific tick bounds
  • Collecting earned trading fees
  • Removing liquidity and burning the position NFT

UniswapV2Module

Protocol: Uniswap V2 (basic AMM) Operations: Swap tokens, add liquidity, remove liquidity

Simpler than V3 — Uniswap V2 uses a constant-product formula without tick ranges.

AaveModule

Protocol: Aave V3 (lending/borrowing) Operations: Supply collateral, borrow assets, repay debt, withdraw

Interacts with Aave's Pool contract through the PoolAddressesProvider. Supports:

  • Supplying tokens as collateral to earn interest
  • Borrowing against supplied collateral
  • Repaying borrowed amounts
  • Withdrawing supplied collateral

MorphoModule

Protocol: Morpho (optimized lending) Operations: Deposit into MetaMorpho vaults, withdraw

Morpho vaults are ERC-4626 compliant, meaning the module uses standard deposit() and withdraw() interfaces.

YearnModule

Protocol: Yearn Finance (yield vaults) Operations: Deposit into Yearn vaults, withdraw

Like Morpho, Yearn uses the ERC-4626 vault standard. The module handles approval and deposit/withdrawal flows.

AerodromeModule

Protocol: Aerodrome (Base chain DEX) Operations: Swap, add liquidity, remove liquidity

Aerodrome is the primary DEX on Base chain. The module supports both standard AMM pools and Slipstream (concentrated liquidity) pools.

RelayModule

Protocol: Gelato Relay Operations: Sponsored/gasless transactions

Enables transactions where gas fees are paid by the platform (via Gelato's relay service) rather than the user. Used for subscription-based automated executions.

CowModule (External)

Protocol: Cow Protocol (MEV-protected swaps) Operations: Approve tokens, sign/unsign orders, wrap/unwrap native tokens

The CowModule is deployed externally — it is not part of the NMT contracts repo. It integrates with Cow Protocol's GPv2Settlement contract using the PRESIGN signing scheme. Since Safes cannot produce ECDSA signatures like EOAs, PRESIGN authorizes orders purely by the Safe executing the call.

Key functions:

  • executeCoWApproval() — approve tokens for the Cow relayer
  • executeCoWSignOrder() — register a PRESIGN order on GPv2Settlement via setPreSignature()
  • executeCoWUnsignOrder() — cancel a pending order
  • executeCoWWrapNative() / executeCoWUnwrapNative() — wrap/unwrap ETH for Cow swaps

Safe-only: Cow Protocol is only available in Safe mode because it requires the PRESIGN scheme.

Chain CowModule Address
Ethereum 0x365485a1Bd944fa155aC2CCfDbC3D56232af3Cc0
Base 0x34f0d479edAA0AB36B90C755010dE7d7B9571629
Arbitrum 0x7F1B5929856633Bf59A493f1Ed5FB46a83d2E486

KrystalModule (External)

Protocol: Krystal (automated liquidity vaults) Operations: Deposit into vaults, withdraw from vaults, approve tokens

The KrystalModule is deployed externally. It integrates with Krystal's automated LP vault protocol, which manages concentrated liquidity positions on Uniswap V3. Vaults follow the ERC-4626 standard.

Key functions:

  • executeKrystalDeposit() — deposit tokens into a Krystal vault
  • executeKrystalWithdraw() — redeem shares from a Krystal vault
  • executeKrystalApproval() — approve tokens for the vault

Note: EOA withdrawals from Krystal vaults are not yet implemented — currently Safe-mode only for withdrawals.

Chain KrystalModule Address
Ethereum 0x11844b2bde4f0f4745DffF52CCBF5f4D808B49a1
Base 0xde229a4F93031624e0F41193aFfF399e1a2DE3D0
Arbitrum 0x872720ecf3519a10F813e1A476d3b53058cc74fd

Key External Addresses

Each module interacts with specific protocol contracts. These addresses differ by chain:

Module Key Contract Base Address
UniswapV3 NonfungiblePositionManager 0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1
UniswapV2 Router 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Aave PoolAddressesProvider 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb
Aerodrome Router 0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43

Testing

Tests are in smart-wallets/test/ and use Hardhat + Chai:

Test Suite Status
PermissionsManager Covered
UniswapV3Module Covered
UniswapV2Module Covered
AaveModule Covered
YearnModule Covered
MorphoModule Not yet covered
AerodromeModule Not yet covered
RelayModule Not yet covered

Contract Location

smart-wallets/contracts/modules/

results matching ""

    No results matching ""