Author: DAOplomats
Status: Draft — Phase 1 (Discussion)
Category: DAO / Treasury
Simple Summary
Authorize collecting the roughly $112,800 in accrued, unclaimed trading fees sitting on the DAO’s 1INCH/WETH Uniswap V3 LP position (NFT #501891, 1% fee tier).
Abstract
The DAO Safe holds a Uniswap V3 liquidity position in the 1INCH/WETH pool (1% fee tier), represented by NFT #501891. Per the Safe’s asset dashboard, the position is currently valued at $258,320.04, made up of:
| Component | Amount | Value |
|---|---|---|
| Deposited principal | 1.66M 1INCH | ~$145,500 |
| Uncollected fees (WETH) | 36.01414 WETH | ~$86,281 |
| Uncollected fees (1INCH) | 303.58K 1INCH | ~$26,534 |
| Total uncollected fees | ~$112,815 |
That’s roughly 43.7% of the position’s total value sitting uncollected ($112,815 ÷ $258,320 ≈ 43.7%) fees that have accrued but never been swept into the treasury. This is a Safe-dashboard snapshot [timeline: 20260916]. This proposal asks the DAO to authorize collecting those fees now.
Motivation
Uniswap V3 fees accrue to a position. Over the past couple months, the position has been more consistently out of range, and an out-of-range Uniswap V3 position accrues zero new fees the balance is frozen, not growing. Thus, this position sits inert until someone calls collect(). They don’t compound and don’t otherwise benefit the treasury while unclaimed. Collecting them now improves treasury custody, visibility, and operational flexibility, and separates already-earned assets from however the LP principal is managed going forward. A follow-up proposal on rebalancing the position’s range is planned but has no scheduled timeline yet.
Rather than leave a meaningful, growing balance unclaimed while that discussion plays out, this proposal asks the DAO to collect it now.
-
It’s idle capital. Uncollected fees aren’t earning anything further while they sit as tokensOwed on the position; they’re just a balance waiting to be swept into the treasury.
-
It’s a meaningful, quantifiable sum. At ~$112,800 (43.7% of the position’s total value; see Abstract), this is large enough to be worth a routine treasury operation rather than being left to accumulate indefinitely.
-
The position appears to be out of range. The Safe’s dashboard shows the deposited principal entirely in 1INCH with no WETH, which is consistent with — but does not itself prove — the pool’s current price sitting outside this position’s tick range. The transaction preparer must confirm this directly by comparing the position’s current tick to tickLower/tickUpper before publication (see the Verification Checklist).
-
Collecting separately, rather than waiting for a rebalance, avoids indefinite delay. No rebalance proposal is currently scheduled and its timeline is undetermined. If one is brought forward on short notice before this executes, the DAO can still choose to combine both actions into a single transaction bundle instead.
This proposal is scoped narrowly to fee collection only. It does not propose withdrawing or rebalancing the underlying 1.66M 1INCH principal that will be the subject of a separate, follow-up proposal to consider adjusting the position’s range so it stays active going forward.
Specification
Execute a collect() call on the Uniswap V3 NonfungiblePositionManager contract for this position, after independently verifying ownership and the claimable balances (see the Verification Checklist tab):
-
Contract: 0xC36442b4a4522E871399CD717aBDD847Ab11FE88 (Uniswap V3: NonfungiblePositionManager, Ethereum mainnet)
-
Position (pool): 1INCH/WETH, 1% fee tier — 0xE931b03260B2854e77e8dA8378A1BC017b13cb97, with
-
token0 = 1INCH, and
-
token1 = WETH
-
-
Token ID: 501891
-
NFT owner: to be confirmed via ownerOf(501891) — must return the executing DAO Safe’s address, or that Safe must hold approved-operator status on the NFT, or the collect() call will revert
-
Recipient: <verified DAO treasury Safe address, confirmed byte-for-byte>
-
Executing Safe: <name/address of the Safe submitting the transaction>
-
Network: Ethereum mainnet
collect(
tokenId: 501891,
recipient: <verified DAO treasury Safe address>,
amount0Max: 340282366920938463463374607431768211455,
amount1Max: 340282366920938463463374607431768211455
)
-
amount0Max / amount1Max above is the literal uint128 maximum (2^128 − 1). Safe Transaction Builder and most wallet interfaces require this exact integer, not Solidity’s type(uint128).max shorthand.
-
Based on the position’s transaction history, the currently claimable balances are believed to consist entirely of accrued trading fees. collect() transfers whatever is currently in tokensOwed0/tokensOwed1, which can also include principal made claimable by a prior decreaseLiquidity() call that was never collected. The transaction preparer must verify from the NFT’s DecreaseLiquidity and Collect event history that no such uncollected principal is included before this is treated as a fees-only action.
-
This authorization does not permit decreasing liquidity, burning or transferring the NFT, approving another operator, swapping either received token, or sending proceeds to any address other than the verified DAO treasury Safe.
-
Following approval, the transaction will be submitted to the identified DAO Safe for execution under its existing signer policy. SafeSnap execution should only be referenced if this specific treasury Safe is confirmed to have an active, correctly configured Reality/SafeSnap module connected — a passed Snapshot vote does not execute a transaction on its own.
-
Position state (tick range, current tick, liquidity, tokensOwed) must be recorded at a specific block number and timestamp immediately before the transaction is prepared, and reconfirmed by simulation immediately before signing.
Rationale
An alternative considered was bundling this with a full range-rebalance in one proposal, since a rebalance’s decreaseLiquidity() and collect() could be executed together in one transaction, saving gas and governance overhead. We chose to split it because no rebalance proposal is currently scheduled and its timeline is undetermined; leaving a meaningful, growing fee balance unclaimed indefinitely while that separate strategy discussion plays out is a worse trade-off than the modest extra gas and signing overhead of a second transaction. If a rebalance is brought forward on short notice before this executes, the DAO can still combine both into one bundle instead.
A second alternative considered was publishing this proposal on the dashboard figures alone, without on-chain verification. We rejected this: collect() transfers whatever is currently in tokensOwed0/tokensOwed1, which can include previously-decreased-but-uncollected principal, not only fees, and a wrong recipient address has no slippage protection to catch it. The Specification and the accompanying Verification Checklist require independent on-chain confirmation of ownership, balances, and recipient before execution.
Considerations
-
Token amounts and USD values above are as of the time of writing and will drift with price before execution; verify the exact collect() output on-chain at execution time rather than assuming it matches the figures here.
-
This proposal does not address why the position has gone out of range or what to do about it — that will be brought as a separate proposal on rebalancing the range.
-
Recipient address for the collected fees needs to be filled in with the correct treasury Safe address, confirmed byte-for-byte, before this is formalized as an official 1IP.
-
Confirm which Safe will execute the transaction and under what signer policy (direct multisig execution vs. a SafeSnap-connected module) — do not assume SafeSnap applies without confirming the module is active for this specific Safe.
-
Add the exact block number and timestamp behind the position figures in the Abstract before this is published.
-
The “Transaction Preparer Verification Checklist” tab must be completed and signed off before execution.
Transaction Preparer Verification Checklist
For NFT #501891 (1INCH/WETH Uniswap V3, 1% fee tier). Every step below must be completed and its result recorded before the collect() transaction is signed.
-
Confirm NFT ownership. Call ownerOf(501891) on the NonfungiblePositionManager (0xC36442b4a4522E871399CD717aBDD847Ab11FE88). Confirm it returns the executing DAO Safe’s address — or that the Safe holds approved-operator status via getApproved/isApprovedForAll — otherwise the direct collect() call will revert.
-
Read the full position state. Call positions(501891) and record token0, token1, fee, tickLower, tickUpper, liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128, tokensOwed0, tokensOwed1.
-
Confirm token ordering and pool identity. Verify token0 = 1INCH and token1 = WETH from step 2, and derive the pool address from token0/token1/fee via the Uniswap V3 Factory — do not rely on a dashboard label for the pool identity.
-
Review the NFT’s event history. Pull every DecreaseLiquidity and Collect event for tokenId 501891. Determine whether tokensOwed0/tokensOwed1 include principal made claimable by a prior decreaseLiquidity() call that was never collected, or whether the current balances are fees-only.
-
Confirm in-range/out-of-range status. Read the pool’s slot0() for the current tick and compare it against tickLower/tickUpper from step 2. State explicitly whether currentTick < tickLower or currentTick >= tickUpper.
-
Record a block number and timestamp. Capture the exact block number and timestamp at which steps 1–5 were performed, and restate the position’s total value and fee breakdown as of that block in the proposal.
-
Verify the treasury recipient address. Confirm the DAO treasury Safe address byte-for-byte against the official, published treasury address. collect() has no slippage protection — a wrong recipient sends the assets to the wrong place with no recovery path.
-
Confirm the executing Safe and its execution policy. Identify whether the transaction will be signed directly by multisig signers or executed via a SafeSnap/Reality module. If SafeSnap, confirm the module is active and correctly configured for this specific Safe before referencing it anywhere in the proposal.
-
Build the transaction with literal parameters. tokenId = 501891, recipient = the verified treasury Safe address, amount0Max = 340282366920938463463374607431768211455, amount1Max = 340282366920938463463374607431768211455. Do not enter Solidity’s type(uint128).max shorthand into a transaction-building interface.
-
Restrict the transaction to collect() alone. Do not include decreaseLiquidity, burn, transferFrom, approve, or any unrelated call in the same multicall or batch.
-
Simulate the exact transaction immediately before signing (e.g., via Tenderly or the Safe’s built-in simulation). Confirm the simulated output amounts and recipient match expectations from steps 2–7.
-
Circulate the simulation result and expected token outputs to all signers before any signature is collected.
-
After execution, publish the transaction hash and final on-chain output amounts publicly, alongside this checklist.
Sign-off
| Step | Completed by | Date | Notes |
|---|---|---|---|
| 1–6 (on-chain verification) | |||
| 7–8 (recipient & execution policy) | |||
| 9–10 (transaction build) | |||
| 11–12 (simulation & signer review) | |||
| 13 (post-execution publication) |