Every approval you sign is a blank check right now. Limes turns it into a boundary you actually control.
Built on Monad Β· BuildAnything Spark Hackathon
Limes (pronounced LEE-mess) is a non-custodial permission gateway for ERC-20 token approvals, built on Monad. It replaces the default model of unlimited, indefinite token approvals with permissions that are capped, time-bound, and instantly revocable. Limes also identifies existing high-risk approvals, allowing users to remove unnecessary permissions before they become an attack vector.
The name is derived from the limes, the fortified frontier system of the Roman Empire. Rather than serving as a wall, the limes was a network of monitored checkpoints that controlled movement across a defined boundary. Limes applies the same principle to token approvals by placing an enforceable permission boundary between users and the applications they authorize.
The problem it addresses is widespread and costly. Forgotten or over-permissioned ERC-20 approvals remain one of the leading causes of wallet drains across the EVM ecosystem. In many cases, users are not compromised through failures of the blockchain itself, but through permissions granted months earlier to applications that are later exploited or become malicious.
Existing tools such as Revoke.cash help users revoke approvals after they already exist. Limes introduces a preventive approach. It is an EVM-native permission layer that enforces approval boundaries entirely on-chain, works with any standard wallet, and prevents excessive permissions from being granted in the first place.
Every interaction with a DeFi application begins with an approve() transaction. Before a DEX, lending protocol, or yield aggregator can spend a user's tokens, the user must authorize the contract through the ERC-20 approval mechanism.
In practice, almost every application requests type(uint256).max, granting unlimited spending authority with no expiration.
This behavior exists because:
- Requiring users to approve every transaction creates significant UX friction.
- The ERC-20
approve()standard has no native support for spending limits or expiration. - Applications have little incentive to request narrower permissions than they need.
As a result, active wallets accumulate dozens of unlimited, long-lived approvals across the ecosystem. Most users have little visibility into which contracts retain spending authority, when those permissions were granted, or how much risk they represent. Every additional approval expands the wallet's attack surface.
| Solution | What it does | Limitation |
|---|---|---|
| Revoke.cash | Audits and revokes existing approvals | Reactive. Users must discover and remove risky approvals after they already exist. |
| Etherscan Approval Checker | Displays current token approvals | Read-only. It provides visibility but does not prevent excessive approvals or help users understand their risk. |
| Safe Allowance Module | Supports capped approvals for Safe multisig wallets | Requires a Safe Smart Account and is not applicable to the vast majority of users with standard EOA wallets. |
| ERC-7710 / ERC-7715 | Introduces wallet-level permission standards | Requires ERC-4337 Smart Accounts and wallet support, making it unavailable to most wallet users today. |
Limes addresses the approval problem at both the prevention and remediation layers.
Prevention
Every approval created through Limes includes an enforced spending cap, a mandatory expiration, and contextual guidance informed by the user's own spending history. Users grant only the permissions they intend, rather than unlimited access by default.
Remediation
Limes continuously helps users reduce existing exposure by scanning for dangerous unlimited approvals across commonly used ERC-20 tokens. Risky permissions can be revoked with a single action, with revocations batched through Multicall3 for efficient execution.
Limes is deployed on the Monad Testnet as a two-contract system with a frontend approval dashboard. Together, these components introduce an enforceable permission layer for ERC-20 approvals without requiring wallet modifications, smart accounts, or changes to existing token contracts.
flowchart LR
U[User Wallet]
subgraph Limes
V[LimesVault]
end
D[dApp]
T[ERC20 Token]
M[Multicall3]
F[Frontend]
U -->|1. Approve Vault Once| T
U -->|2. Create Permission| V
D -->|3. Request Payment| V
V -->|Validate Cap, Expiry, Revocation| V
V -->|4. transferFrom| T
T --> D
F -->|Approval Scanner| M
M -->|Batch allowance reads| T
T --> F
The vault is the execution layer for token transfers. Users grant a single ERC-20 approval to the vault, after which every spend is validated against the permission rules recorded in the registry.
LimesVault is the core permission gateway. It is entirely non-custodial and never holds user funds. Its sole responsibility is to enforce permission rules before executing transferFrom() calls.
Key properties include:
- Every permission requires a spending cap and expiration, with optional recurring periods for budget-based permissions.
revoke()remains callable even when the contract is paused, ensuring users always retain an immediate kill switch.- For Demo: A hardcoded
MAX_FEE_BPS = 500caps protocol fees at 5%, regardless of owner privileges or future configuration changes. - Built on OpenZeppelin's
OwnableandPausablecontracts for operational safety. During an incident, new permissions and token pulls can be paused while revocations remain fully functional. - Uses
ReentrancyGuardto protect all external state-changing functions.
LimesSubscription is a reference integration that demonstrates how applications can integrate with Limes for recurring payments.
It provides a complete end-to-end subscription flow while guaranteeing that an application can never spend more than the user explicitly authorized or continue charging after the permission expires.
The reference implementation includes:
- Protection against duplicate charges from repeated
subscribe()calls. - Support for resubscription once a previous permission has expired or been revoked.
- Treasury settlement through
withdraw(), where collected fees can only be transferred to the immutable treasury address defined at deployment.
MockUSD is a freely mintable ERC-20 token used exclusively for demonstrations on Monad Testnet.
It allows judges, developers, and beta users to exercise the complete permission flow without relying on external faucets or third-party test tokens.
The frontend is implemented as a single HTML and JavaScript application using ethers.js v6.
It requires no build system or framework, making the entire interface easy to inspect, audit, and run locally.
Features include:
- Wallet connection with automatic switching to Monad Testnet.
- A contextual approval interface with configurable spending caps, expiration periods, and live dollar exposure estimates.
- A complete permission lifecycle covering Grant β Subscribe β Revoke β Resubscribe.
- A permission history view powered by
getOwnerPermissions(), displaying every permission together with its current status. - An approval scanner that:
- indexes
Approvalevent logs for supported tokens, - batches all
allowance()queries throughMulticall3in a single RPC request, and - identifies active and unlimited approvals with one-click revocation.
- indexes
hdhjkvcjedfnljkkdfnknfgknedsfgkniowqwfknkewfk
Limes introduces several architectural decisions that distinguish it from existing approval management tools and wallet permission systems.
Most approval management tools are reactive. They help users discover and revoke permissions only after those approvals have already been granted.
Limes moves protection to the point where the permission is created. Every approval is defined with an explicit spending cap and expiration before it becomes valid, preventing unlimited permissions from existing in the first place.
Limes never takes custody of user assets.
LimesVault does not hold balances or act as an intermediary wallet. Tokens remain in the user's own address at all times. The vault's only responsibility is to enforce permission rules before executing transferFrom() calls authorized through a standard ERC-20 approval.
Because the approval itself remains under the user's control, it can be revoked at any time.
The approval scanner is built for efficiency.
Instead of issuing separate allowance() RPC requests for every token and spender combination, Limes batches all reads into a single aggregate3 call through the canonical Multicall3 contract on Monad.
This significantly reduces network overhead while demonstrating a practical integration with Monad infrastructure.
Operational safety and user safety are treated independently.
If a critical vulnerability is discovered, protocol administrators can pause new permissions and token pulls to prevent further impact. However, revoke() intentionally bypasses the pause mechanism, ensuring users always retain the ability to invalidate their own permissions.
The protocol pause protects the system. The revoke function protects the user.
| Technology | Role | Why It Was Chosen |
|---|---|---|
| Solidity 0.8.24 | Smart contract development | Latest stable compiler with built-in overflow protection, custom errors, and a mature tooling ecosystem. |
| Monad Testnet (Chain ID 10143) | Deployment target | Monad's sub-second finality and low transaction costs make per-permission enforcement economically practical. Validating spending limits on every token pull would be prohibitively expensive on Ethereum mainnet. |
| OpenZeppelin Contracts v5 | Security primitives (ReentrancyGuard, Ownable, Pausable, IERC20) |
Industry-standard, extensively audited implementations that eliminate the need to reimplement fundamental security components. |
| Hardhat 2.22 | Development, testing, deployment, and verification | Mature Ethereum development framework with reliable debugging, deployment workflows, and native Sourcify support. |
| Sourcify | Contract verification | Official verification path for Monad through sourcify-api-monad.blockvision.org, providing full source verification and transparent on-chain inspection. |
Multicall3 (0xcA11...CA11) |
Batched allowance() reads |
Canonical Monad deployment used to aggregate multiple allowance queries into a single aggregate3 call, reducing RPC overhead while demonstrating a practical integration with Monad infrastructure. |
| ethers.js v6 | Frontend blockchain interaction | Widely adopted Ethereum library with native support for Monad's EVM-compatible RPC interface. |
| Tailwind CSS (CDN) | Frontend styling | Enables a lightweight, build-free frontend distributed as a single static HTML file. |
| Chai + Hardhat Network Helpers | Testing framework | Powers a comprehensive suite of 21 passing tests covering the security guarantees, permission lifecycle, and expected contract behavior. |
flowchart TD
U["User Wallet"]
V["LimesVault"]
U -->|"Approve Once"| V
U -->|"Create Permission"| V
V -->|"Validated Pull"| S["LimesSubscription"]
V -->|"Validated Pull"| D["Any dApp"]
S --> T["ERC20 Token"]
D --> T
T --> X["Protocol Treasury"]
Each permission stores:
- owner
- spender
- token
- cap
- spent
- period
- periodStart
- expiry
- revoked
Connect your wallet to Limes. If you are not already on Monad Testnet, the application automatically prompts you to switch networks.
Once connected, the frontend immediately:
- retrieves your permission history from
LimesVault, - scans your wallet for existing ERC-20 approvals across supported tokens, and
- batches all
allowance()queries into a singleMulticall3request for efficient retrieval.
Specify a spending cap and an expiration period. For example, you might authorize 250 mUSD for 30 days.
As you adjust these values, the interface updates the Maximum Dollar Exposure estimate in real time. When ready, click Create Bounded Approval.
Behind the scenes, three transactions execute sequentially:
MockUSD.mint()mints test tokens if your balance is below the requested spending cap.MockUSD.approve(LimesVault, MaxUint256)grants the vault its one-time ERC-20 approval. This approval is not repeated for future permissions.LimesVault.grantPermission(LimesSubscription, mUSD, cap, 0, expiry)creates the bounded permission by recording its spending cap and expiration on-chain.
Click Subscribe Now to demonstrate permission enforcement.
This invokes LimesSubscription.subscribe(permissionId), which internally calls:
LimesVault.pull(id, 5e18)Before transferring any tokens, the vault verifies that:
- the permission is still active,
- the spending cap has not been exceeded, and
- the permission has not expired.
Only after all checks succeed does the vault execute the underlying transferFrom() call. The subscription contract cannot spend more than the user explicitly authorized.
Click Revoke Permission to immediately invalidate the approval.
This submits a single transaction:
LimesVault.revoke(id)After the transaction is confirmed, any subsequent attempt to subscribe fails on-chain because the permission has been revoked.
The spending limit is enforced by the protocol itself rather than by frontend logic or application behavior.
The Approval Scanner analyzes ERC-20 approvals that were granted outside of Limes.
For every approval it discovers, the scanner displays:
- the token,
- the spender address, and
- whether the allowance is unlimited.
Selecting Revoke submits an approve(spender, 0) transaction directly to the underlying ERC-20 token contract, permanently resetting that allowance on-chain.
The following contracts are deployed on Monad Testnet and verified through Sourcify.
| Contract | Address | Verification |
|---|---|---|
| MockUSD | 0xf5cebCa6b269183A3976136E52752E6AC4ee5Fae |
View on Sourcify |
| LimesVault | 0xD7E3ac3340528B67C444920488f69627693E76e5 |
View on Sourcify |
| LimesSubscription | 0x18032362b1b1F30bF39850668915a1f14A2A04D2 |
View on Sourcify |
All contracts are fully verified on Sourcify with source-bytecode full match.
Limes includes a comprehensive test suite with 21 passing tests across two test files. Every security guarantee and permission rule enforced by the contracts is verified through automated tests.
npx hardhat testThe LimesVault test suite verifies the protocol's core security model and permission enforcement.
- Deploys with the configured treasury and initial protocol fee while enforcing the maximum fee ceiling.
- Deducts the protocol fee during
pull(), with the fee counted against the user's total spending cap. - Rejects
grantPermission()andpull()while the contract is paused, while ensuringrevoke()remains available. - Restricts administrative operations such as pausing, fee updates, and treasury changes to the contract owner.
- Creates permissions with the expected on-chain fields.
- Allows the authorized spender to transfer tokens within the approved spending cap.
- Rejects transfers that exceed the remaining spending limit.
- Rejects transfers initiated by unauthorized spenders.
- Rejects transfers after a permission has expired.
- Allows the permission owner to revoke access immediately, preventing all future transfers.
- Rejects revocation attempts from accounts other than the permission owner.
- Resets the available spending budget when a recurring permission enters a new billing period.
The LimesSubscription test suite validates the reference recurring payment integration built on top of Limes.
- Successfully creates a subscription and charges the first billing cycle for exactly
PRICE. - Rejects attempts to charge the next billing cycle before it becomes due.
- Processes subsequent billing cycles when eligible while continuing to enforce the original spending cap.
- Rejects charges after the user's approved budget has been exhausted.
- Rejects charges after the user revokes the underlying permission during an active subscription.
- Rejects duplicate
subscribe()calls while an active permission already exists. - Allows users to create a new subscription immediately after revoking the previous permission.
- Allows any caller to execute
withdraw(), transferring the full contract balance to the immutable treasury address. - Rejects
withdraw()when no funds are available for withdrawal.
Before getting started, ensure you have:
- Node.js 18 or later
- MetaMask or another EVM-compatible wallet
- A Monad Testnet wallet funded with testnet MON (available from the official Monad faucet)
git clone https://github.com/phllp-tanstic/limes-protocol
cd limes-protocol
npm installCopy the example environment file and provide your credentials.
cp .env.example .envUpdate .env with:
PRIVATE_KEY=<your_private_key>
MONAD_TESTNET_RPC=<your_rpc_endpoint>
Compile the contracts:
npx hardhat compileRun the full test suite:
npx hardhat testDeploy all contracts:
npx hardhat run scripts/deploy.js --network monadTestnetVerify each deployed contract through Sourcify:
npx hardhat verify --network monadTestnet <MOCK_USD_ADDRESS>
npx hardhat verify --network monadTestnet \
<VAULT_ADDRESS> \
<OWNER> \
<TREASURY> \
0
npx hardhat verify --network monadTestnet \
<SUBSCRIPTION_ADDRESS> \
<VAULT_ADDRESS> \
<TREASURY>Navigate to the frontend directory and serve the application locally.
cd ../limes-frontend
npx serve .The application will be available at:
http://localhost:3000
Integrate on-chain security intelligence from providers such as Blockaid, GoPlus, or Forta to continuously evaluate approved spenders.
Beyond displaying existing approvals, Limes will identify approvals that become risky over time by monitoring signals including:
- contract upgrades,
- ownership transfers,
- significant TVL declines, and
- confirmed security incidents.
This allows users to react to changing protocol risk, even when the original approval was granted safely.
Introduce an oracle-driven emergency response system for compromised protocols.
When a trusted security oracle confirms that a protocol has been exploited, every LimesVault permission associated with that spender can be automatically quarantined. Quarantined permissions cannot execute transfers until the user explicitly reviews or permanently revokes them.
The underlying architecture already supports this model through the existing pause mechanism and permission controls. The remaining component is a trusted external security feed.
Recommend spending limits based on each user's historical on-chain activity.
Instead of requesting unlimited approvals, Limes will analyze previous interactions with a protocol and suggest an appropriate cap.
For example:
You've spent approximately $180 with this protocol over the last 30 days. Consider approving $250 instead of an unlimited allowance.
These recommendations can be generated entirely from on-chain transaction history without relying on third-party user data.
Expand the current demonstration interface into a comprehensive permission management platform.
Planned capabilities include:
- multi-wallet support,
- complete permission history,
- spending analytics,
- expiration countdowns,
- dormant permission detection, and
- batch approval management.
Introduce PolicyGuard, an organizational policy layer built on top of Limes.
Organizations will be able to define approval policies across treasury wallets, including:
- prohibiting unlimited approvals,
- enforcing maximum spending caps,
- requiring expiration periods, and
- standardizing approval policies across teams.
This targets DAOs, crypto funds, and companies managing on-chain treasury operations while establishing Limes' enterprise offering.
Deploy Limes to production following a professional security audit.
The protocol architecture has been intentionally designed with a small attack surface and minimal contract complexity to simplify auditing and strengthen security before mainnet release.
The current approval scanner indexes a limited set of ERC-20 tokens on Monad Testnet.
Production deployments will replace this with a dedicated indexing service that continuously tracks Approval events across the entire network, enabling discovery and monitoring of approvals for any supported ERC-20 contract.
Limes is designed around a tiered product model that serves both individual users and organizations.
| Tier | Features |
|---|---|
| Free | Permission management, approval scanner, and on-chain revocation tools. |
| Pro | Real-time notifications when new unlimited approvals are detected, plus periodic reports highlighting dormant or high-risk permissions. |
| Business | Organization-wide approval policies, team dashboards, administrative controls, and a Limes Verified integration program for applications that commit to requesting bounded permissions instead of unlimited approvals. |
The Limes Verified designation creates a trust signal for users while encouraging applications to adopt safer approval practices, reinforcing a network effect between users and protocol integrations.
| Technology | Version | Purpose |
|---|---|---|
| βοΈ Monad | Testnet (Chain ID 10143) | Layer 1 deployment target. Monad's sub-second finality and low transaction costs make per-permission enforcement economically practical. |
| π Solidity | 0.8.24 | Smart contract development. |
| π¨ Hardhat | 2.22 | Contract compilation, testing, deployment, and verification. |
| π‘οΈ OpenZeppelin Contracts | 5.x | Security primitives including ReentrancyGuard, Ownable, and Pausable. |
| π¦ Multicall3 | Canonical deployment | Batched allowance() queries used by the approval scanner. |
| β Sourcify | Monad integration | Full source contract verification. |
| π ethers.js | 6.x | Frontend interaction with deployed contracts. |
| π¨ Tailwind CSS | CDN | Frontend styling without a build step. |
| π§ͺ Chai | Latest | Smart contract test assertions. |
Most wallet drains do not begin with a compromised blockchain. They begin with a permission that was granted months earlier, forgotten over time, and left with unlimited spending authority.
Limes changes that model by making bounded permissions the default. Users grant a single approval to the vault, while every subsequent permission is constrained by explicit spending limits and expiration. Existing approvals are continuously surfaced, allowing unnecessary or dangerous permissions to be revoked before they become an attack vector.
Monad makes this architecture practical. Enforcing spending limits requires an on-chain permission check for every token transfer. On networks with high transaction costs, this model becomes prohibitively expensive for everyday activity. Monad's low fees and sub-second finality make continuous permission enforcement economically viable.
The protocol is non-custodial, fully verified, and backed by comprehensive automated tests. Its architecture prioritizes a small audit surface, an immutable protocol fee ceiling, emergency controls that preserve user revocation rights, and a clear path toward organizational policy management without redesigning the core protocol.
Limes is the foundation of a permission infrastructure layer for the EVM, bringing enforceable boundaries to ERC-20 approvals without requiring new wallet standards or changes to existing token contracts.
Built for the BuildAnything Spark Hackathon* β’ Deployed on Monad Testnet