Skip to content

Conversation

@o0j4yj4y0o
Copy link

@o0j4yj4y0o o0j4yj4y0o commented Jan 23, 2026

Summary

Comprehensive fees adapter for Olympus DAO tracking all protocol revenue sources across multiple chains using an additive approach (direct measurement of each revenue stream).

Revenue Sources Tracked

Ethereum:

Source Method Description
Cooler Loan Interest Accumulator delta × totalDebt Interest on OHM-backed loans
sUSDS Yield ERC-4626 rate delta × balance Treasury holdings in Sky's savings USDS
sUSDe Yield ERC-4626 rate delta × balance Treasury holdings in Ethena's staked USDe
CD Facility Yield ClaimedYield events Yield harvested from convertible deposits
CD Lending Interest LoanRepaid events Interest from loans against pending redemptions
POL Fees Uniswap V3 Collect events LP fees from OHM/wETH and OHM/sUSDS positions

Base:

Source Method Description
POL Fees Uniswap V3 Collect events LP fees from OHM/USDC position

Arbitrum:

Source Method Description
POL Fees Camelot V2 Swap events × 0.25% LP fees from WETH/OHM pool

Key Design Decisions

  1. Additive Approach: Directly tracks each revenue source rather than backing into fees from aggregate metrics
  2. Multi-chain: Supports Ethereum, Base, and Arbitrum
  3. 100% Holders Revenue: All revenue benefits OHM holders through increased treasury backing
  4. Modular Architecture: Chain-specific config object and reusable helper functions

Pending Revenue Note

CD Lending currently has ~$437k in outstanding loans with ~$6k in fixed interest. This interest will be realized when loans mature (April-May 2026) and automatically captured via LoanRepaid events.

Test Results

chain     | Daily fees | Daily revenue | Daily holders revenue
ethereum  | 3.92 k     | 3.92 k        | 3.92 k
base      | 0.00       | 0.00          | 0.00
arbitrum  | 2.00       | 2.00          | 2.00
Aggregate | 3.93 k     | 3.93 k        | 3.93 k

Test plan

  • Tested with multiple dates to verify consistent tracking
  • Verified each revenue source captures expected events
  • Confirmed multi-chain functionality
  • Validated all revenue marked as holders revenue

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added multi-chain Olympus DAO fee adapter supporting Ethereum, Base, and Arbitrum.
    • Enables tracking of revenue streams including loan interest, yield farming returns, and protocol-owned liquidity fees across supported chains.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

A new Olympus DAO Fees Adapter is introduced that tracks fee and revenue metrics across Ethereum, Base, and Arbitrum. The adapter fetches data from multiple on-chain sources including Cooler loans, ERC-4626 yield contracts, CD Facility, and liquidity pool positions, then aggregates the collected metrics into daily summaries.

Changes

Cohort / File(s) Summary
Olympus DAO Fees Adapter
fees/olympus-dao.ts
New adapter implementing multi-chain fee tracking for Ethereum (Cooler loan interest, ERC-4626 yields, CD Facility yields, POL fees), Base (POL fees via Uniswap V3), and Arbitrum (Camelot V2 POL fees via swap events). Includes chain-specific configurations, ABIs, event handlers, and data-fetch pipelines with aggregation logic.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 A new adapter hops into place,
Tracking OHM fees across blockchain space,
From Ethereum yields to Base's bright light,
Arbitrum swaps dancing through the night,
OlympusDAO's revenue now in sight! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the primary change: introducing a comprehensive, multi-chain fees adapter for Olympus DAO with an additive approach.
Description check ✅ Passed The PR description comprehensively documents the adapter implementation with revenue sources, test results, design decisions, and test verification—well beyond the template requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@llamabutler
Copy link

The olympus-dao.ts adapter exports:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees olympus-dao.ts

🦙 Running OLYMPUS-DAO.TS adapter 🦙
---------------------------------------------------
Start Date:	Thu, 22 Jan 2026 13:29:44 GMT
End Date:	Fri, 23 Jan 2026 13:29:44 GMT
---------------------------------------------------

ETHEREUM 👇
Backfill start time: 1/1/2023
Daily fees: 9.96 k
Daily revenue: 9.96 k
Daily holders revenue: 9.96 k
End timestamp: 1769174983 (2026-01-23T13:29:43.000Z)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @.ralph/IMPLEMENTATION_PLAN.md:
- Around line 17-18: The implementation plan currently states sUSDe/POL revenues
should go to dailyProtocolRevenue and not HoldersRevenue, but the adapter routes
all revenue to dailyHoldersRevenue; update the IMPLEMENTATION_PLAN.md tasks
(Tasks 7–8) to reflect the actual routing by replacing references to
dailyProtocolRevenue and “not HoldersRevenue” with the implemented
dailyHoldersRevenue behavior, explicitly noting that sUSDe yield and POL
(Uniswap V3) fees are included in dailyFees and aggregated under
dailyHoldersRevenue via the adapter, and mention the adapter as the source of
truth for routing decisions.

In `@fees/olympus-dao.ts`:
- Around line 114-119: The bond deposit handling loop (iterating bondLogs)
currently adds bondAmount to dailyFees and dailyRevenue but omits
dailyHoldersRevenue; update the loop where bondAmount is derived (const
bondAmount = log.amount) to also call dailyHoldersRevenue.add(CONTRACTS.dai,
bondAmount) so Bond revenue is treated as 100% holder-benefiting revenue
consistent with YRF buybacks, POL fees, and sUSDe yield handling.
- Around line 96-103: The repo market handling currently treats RepoMarket
bidAmount as DAI; update the logic to record these amounts as USDS instead:
replace uses of CONTRACTS.dai with CONTRACTS.usds when adding bidAmount from
repoMarketLogs (affecting dailyFees.add, dailyRevenue.add,
dailyHoldersRevenue.add for the loop that reads log.bidAmount). Also review
similar bond depository handling to ensure each market/bond resolves its actual
quote/reserve token rather than assuming DAI — if markets can use different
reserve tokens, switch to resolving per-market reserve token before calling
dailyFees.add/dailyRevenue.add/dailyHoldersRevenue.add.
🧹 Nitpick comments (1)
fees/olympus-dao.ts (1)

141-168: Cache Uniswap V3 position lookups to reduce RPC load.

Each Collect log triggers a positions() call; repeated tokenIds will cause redundant calls and slow daily runs. Cache token0/token1 by tokenId.

♻️ Suggested refactor
-    // Process each collect event - need to look up token pair for each position
-    for (const log of treasuryCollects) {
-      const tokenId = log.tokenId;
+    // Process each collect event - need to look up token pair for each position
+    const positionCache = new Map<string, { token0: string; token1: string }>();
+    for (const log of treasuryCollects) {
+      const tokenId = String(log.tokenId);
       const amount0 = log.amount0;
       const amount1 = log.amount1;

       // Get position details to know which tokens were collected
       try {
-        const position = await options.api.call({
-          abi: ABIS.positions,
-          target: CONTRACTS.uniswapV3PositionManager,
-          params: [tokenId],
-        });
-
-        const token0 = position.token0;
-        const token1 = position.token1;
+        let position = positionCache.get(tokenId);
+        if (!position) {
+          const rawPosition = await options.api.call({
+            abi: ABIS.positions,
+            target: CONTRACTS.uniswapV3PositionManager,
+            params: [tokenId],
+          });
+          position = { token0: rawPosition.token0, token1: rawPosition.token1 };
+          positionCache.set(tokenId, position);
+        }
+
+        const { token0, token1 } = position;

Comment on lines 17 to 18
- [x] Task 7: Integrate sUSDe yield into dailyFees and dailyProtocolRevenue - Add the calculated sUSDe yield to the fee tracking (not HoldersRevenue)
- [x] Task 8: Integrate POL fees into dailyFees and dailyProtocolRevenue - Add collected Uniswap V3 fees to protocol revenue tracking
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Implementation plan conflicts with holdersRevenue routing.

Tasks 7–8 say sUSDe/POL should not hit HoldersRevenue and reference dailyProtocolRevenue, but the adapter now routes all revenue to dailyHoldersRevenue. Please update the plan to match the implemented methodology.

🤖 Prompt for AI Agents
In @.ralph/IMPLEMENTATION_PLAN.md around lines 17 - 18, The implementation plan
currently states sUSDe/POL revenues should go to dailyProtocolRevenue and not
HoldersRevenue, but the adapter routes all revenue to dailyHoldersRevenue;
update the IMPLEMENTATION_PLAN.md tasks (Tasks 7–8) to reflect the actual
routing by replacing references to dailyProtocolRevenue and “not HoldersRevenue”
with the implemented dailyHoldersRevenue behavior, explicitly noting that sUSDe
yield and POL (Uniswap V3) fees are included in dailyFees and aggregated under
dailyHoldersRevenue via the adapter, and mention the adapter as the source of
truth for routing decisions.

@llamabutler
Copy link

The olympus-dao.ts adapter exports:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees olympus-dao.ts

🦙 Running OLYMPUS-DAO.TS adapter 🦙
---------------------------------------------------
Start Date:	Thu, 22 Jan 2026 14:02:14 GMT
End Date:	Fri, 23 Jan 2026 14:02:14 GMT
---------------------------------------------------

ETHEREUM 👇
Backfill start time: 1/1/2023
Daily fees: 9.96 k
Daily revenue: 9.96 k
Daily holders revenue: 9.96 k
End timestamp: 1769176933 (2026-01-23T14:02:13.000Z)

@llamabutler
Copy link

The olympus-dao.ts adapter exports:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees olympus-dao.ts

🦙 Running OLYMPUS-DAO.TS adapter 🦙
---------------------------------------------------
Start Date:	Thu, 22 Jan 2026 22:24:57 GMT
End Date:	Fri, 23 Jan 2026 22:24:57 GMT
---------------------------------------------------

chain     | Daily fees | Daily revenue | Daily holders revenue | Start Time
---       | ---        | ---           | ---                   | ---       
ethereum  | 3.92 k     | 3.92 k        | 3.92 k                | 1/1/2023  
base      | 0.00       | 0.00          | 0.00                  | 1/1/2024  
arbitrum  | 2.00       | 2.00          | 2.00                  | 1/1/2024  
Aggregate | 3.93 k     | 3.93 k        | 3.93 k                |           

@o0j4yj4y0o o0j4yj4y0o changed the title feat: add Olympus DAO fees adapter feat: Olympus DAO comprehensive fees adapter (multi-chain, additive approach) Jan 24, 2026
@llamabutler
Copy link

The olympus-dao.ts adapter exports:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees olympus-dao.ts

🦙 Running OLYMPUS-DAO.TS adapter 🦙
---------------------------------------------------
Start Date:	Thu, 22 Jan 2026 22:35:56 GMT
End Date:	Fri, 23 Jan 2026 22:35:56 GMT
---------------------------------------------------

chain     | Daily fees | Daily revenue | Daily holders revenue | Start Time
---       | ---        | ---           | ---                   | ---       
ethereum  | 3.92 k     | 3.92 k        | 3.92 k                | 1/1/2023  
base      | 0.00       | 0.00          | 0.00                  | 1/1/2024  
arbitrum  | 2.00       | 2.00          | 2.00                  | 1/1/2024  
Aggregate | 3.92 k     | 3.92 k        | 3.92 k                |           

Implements a multi-chain fees adapter for Olympus DAO tracking all protocol
revenue sources using an additive approach.

Revenue sources tracked:

Ethereum:
- Cooler Loan interest (MonoCooler accumulator delta method)
- sUSDS yield (ERC-4626 exchange rate method)
- sUSDe yield (ERC-4626 exchange rate method)
- CD Facility yield (ClaimedYield events)
- CD Lending interest (LoanRepaid events)
- POL fees from Uniswap V3 positions (OHM/WETH, OHM/sUSDS)

Base:
- POL fees from Uniswap V3 (OHM/USDC)

Arbitrum:
- POL fees from Camelot V2 (WETH/OHM swap volume)

Key implementation details:
- All revenue classified as holders revenue (backs OHM treasury)
- Fixes CD Facility/sUSDS yield overlap to prevent ~0.02% double counting
- Uses event-based tracking for claimed yields and loan repayments
- Supports multiple treasury addresses per chain

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@o0j4yj4y0o o0j4yj4y0o force-pushed the feat/olympus-dao-adapter branch from f6ae4d5 to 6067e33 Compare January 26, 2026 15:38
@llamabutler
Copy link

The olympus-dao.ts adapter exports:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees olympus-dao.ts

🦙 Running OLYMPUS-DAO.TS adapter 🦙
---------------------------------------------------
Start Date:	Sun, 25 Jan 2026 13:09:07 GMT
End Date:	Mon, 26 Jan 2026 13:09:07 GMT
---------------------------------------------------

chain     | Daily fees | Daily revenue | Daily holders revenue | Start Time
---       | ---        | ---           | ---                   | ---       
ethereum  | 5.13 k     | 5.13 k        | 5.13 k                | 1/1/2023  
base      | 0.00       | 0.00          | 0.00                  | 1/1/2024  
arbitrum  | 11.00      | 11.00         | 11.00                 | 1/1/2024  
Aggregate | 5.14 k     | 5.14 k        | 5.14 k                |           

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@fees/olympus-dao.ts`:
- Around line 436-454: The code assumes Olympus owns ~100% of the Camelot V2 LP
but never validates that, so either document the assumption or adjust fee
calculation by scaling with actual LP ownership; update the block using
FEE_RATE, swapLogs, and fees.add to (a) add a clear comment near FEE_RATE
stating this is a hardcoded assumption and a TODO to validate ownership, or (b)
implement a runtime check that queries the pool for totalSupply and Olympus LP
token balance, compute ownershipShare = olympusBalance / totalSupply and
multiply fee0/fee1 by ownershipShare before calling fees.add (use
CHAIN_CONFIG.arbitrum addresses to identify tokens). Ensure the chosen approach
is clearly noted in comments and that any new async lookup is performed before
iterating swapLogs.
🧹 Nitpick comments (3)
fees/olympus-dao.ts (3)

180-189: Potential timing inconsistency in Cooler interest calculation.

The calculation uses totalDebt at period end (api.call) but measures accumulator delta across the period. If debt changed significantly during the period, this could over/understate interest. For more accurate measurement, consider using average debt or the debt at period start.

However, given that debt changes are likely gradual and this is a daily adapter, the impact should be minimal.


214-223: Balance snapshot timing may affect yield accuracy.

The function uses api (end-of-period) for balance but measures rate delta across the period. If the treasury deposited/withdrew during the period, this could slightly over/understate yield. For higher accuracy, consider using average balance or start-of-period balance.

This is a minor concern since deposits/withdrawals are infrequent for treasury positions.


365-420: Unused function fetchCamelotPOLFees.

This function is defined but never called anywhere in the adapter. The Arbitrum fetch uses fetchCamelotV2Fees instead. If this was intended for Camelot V3/Algebra positions, it should be integrated; otherwise, remove it to reduce dead code.

♻️ Suggested action

Either remove the unused function:

-/**
- * Fetch Camelot (Algebra) POL fees on Arbitrum
- */
-async function fetchCamelotPOLFees(
-  options: FetchOptions,
-  nftManager: string,
-  treasuryAddresses: string[]
-) {
-  const fees = options.createBalances();
-
-  try {
-    const collectLogs = await options.getLogs({
-      target: nftManager,
-      eventAbi: EVENTS.algebraCollect,
-    });
-
-    // Filter for collects where recipient is a treasury address
-    const treasuryCollects = collectLogs.filter(
-      (log: any) => treasuryAddresses.includes(log.recipient.toLowerCase())
-    );
-
-    // Cache position lookups
-    const positionCache = new Map<string, { token0: string; token1: string }>();
-
-    for (const log of treasuryCollects) {
-      const tokenId = String(log.tokenId);
-      const amount0 = log.amount0;
-      const amount1 = log.amount1;
-
-      try {
-        let positionData = positionCache.get(tokenId);
-        if (!positionData) {
-          const position = await options.api.call({
-            abi: ABIS.algebraPositions,
-            target: nftManager,
-            params: [tokenId],
-          });
-          positionData = { token0: position.token0, token1: position.token1 };
-          positionCache.set(tokenId, positionData);
-        }
-
-        const { token0, token1 } = positionData;
-
-        if (BigInt(amount0) > 0) {
-          fees.add(token0, amount0);
-        }
-        if (BigInt(amount1) > 0) {
-          fees.add(token1, amount1);
-        }
-      } catch (e) {
-        // Position may have been burned
-      }
-    }
-  } catch (e) {
-    // POL fee tracking may fail in periods with no collects
-  }
-
-  return fees;
-}

Or if Camelot V3/Algebra positions exist, integrate it into fetchArbitrum.

Comment on lines +436 to +454
// Camelot V2 fee is 0.3% (30 bps) of input amounts
// Since Olympus owns ~100% of LP, they earn ~100% of LP fees
// LP fees are typically 0.25% (protocol takes 0.05%)
const FEE_RATE = BigInt(25); // 0.25% = 25 bps
const BPS = BigInt(10000);

for (const log of swapLogs) {
const amount0In = BigInt(log.amount0In);
const amount1In = BigInt(log.amount1In);

// Fee is calculated on input amount
if (amount0In > 0) {
const fee0 = (amount0In * FEE_RATE) / BPS;
fees.add(CHAIN_CONFIG.arbitrum.weth, fee0);
}
if (amount1In > 0) {
const fee1 = (amount1In * FEE_RATE) / BPS;
fees.add(CHAIN_CONFIG.arbitrum.ohm, fee1);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

git ls-files | grep -i olympus

Repository: DefiLlama/dimension-adapters

Length of output: 91


🏁 Script executed:

find . -type f -name "*olympus*" -o -name "fees" -type d

Repository: DefiLlama/dimension-adapters

Length of output: 100


🏁 Script executed:

fd "olympus" --type f

Repository: DefiLlama/dimension-adapters

Length of output: 91


🏁 Script executed:

rg "Camelot.*V2|0x8acd42e4b5a5750b44a28c5fb50906ebff145359" -i --type ts

Repository: DefiLlama/dimension-adapters

Length of output: 1279


🏁 Script executed:

rg "fetchCamelotV2Fees|FEE_RATE.*25" --type ts -B 5 -A 10

Repository: DefiLlama/dimension-adapters

Length of output: 4466


🏁 Script executed:

cat -n fees/olympus-dao.ts | head -100

Repository: DefiLlama/dimension-adapters

Length of output: 4361


🏁 Script executed:

cat -n fees/olympus-dao.ts | tail -100

Repository: DefiLlama/dimension-adapters

Length of output: 3909


🏁 Script executed:

wc -l fees/olympus-dao.ts

Repository: DefiLlama/dimension-adapters

Length of output: 95


🏁 Script executed:

sed -n '420,470p' fees/olympus-dao.ts

Repository: DefiLlama/dimension-adapters

Length of output: 1534


🏁 Script executed:

rg "ownership|totalSupply|balanceOf|LP.*100|Olympus.*own" fees/olympus-dao.ts -B 2 -A 2

Repository: DefiLlama/dimension-adapters

Length of output: 919


🏁 Script executed:

rg "0x8acd42e4b5a5750b44a28c5fb50906ebff145359|camelotV2Pool" --type ts -B 3 -A 3

Repository: DefiLlama/dimension-adapters

Length of output: 829


🏁 Script executed:

head -150 fees/olympus-dao.ts

Repository: DefiLlama/dimension-adapters

Length of output: 6132


🏁 Script executed:

rg "liquidity|LP.*token|share|lpToken" fees/olympus-dao.ts -B 2 -A 2

Repository: DefiLlama/dimension-adapters

Length of output: 1195


🏁 Script executed:

sed -n '380,430p' fees/olympus-dao.ts

Repository: DefiLlama/dimension-adapters

Length of output: 1530


🏁 Script executed:

sed -n '427,470p' fees/olympus-dao.ts

Repository: DefiLlama/dimension-adapters

Length of output: 1329


🏁 Script executed:

rg "lpToken|liquidity.*balance|totalSupply.*arbitrum" fees/olympus-dao.ts

Repository: DefiLlama/dimension-adapters

Length of output: 54


🏁 Script executed:

rg "ownership|LP.*balance|share.*protocol" dexs/ fees/ --type ts -l | head -5

Repository: DefiLlama/dimension-adapters

Length of output: 173


🏁 Script executed:

fd "camelot" --type f | head -10

Repository: DefiLlama/dimension-adapters

Length of output: 90


🏁 Script executed:

cat -n dexs/camelot/index.ts | head -80

Repository: DefiLlama/dimension-adapters

Length of output: 3180


🏁 Script executed:

rg "100%|ownership|LP.*Olympus" fees/olympus-dao.ts

Repository: DefiLlama/dimension-adapters

Length of output: 332


🏁 Script executed:

sed -n '1,100p' fees/camelot-v3.ts

Repository: DefiLlama/dimension-adapters

Length of output: 137


🏁 Script executed:

rg "Olympus.*LP|LP.*ownership|100%.*LP" . --type ts --type md

Repository: DefiLlama/dimension-adapters

Length of output: 3012


🏁 Script executed:

grep -r "0x8acd42e4b5a5750b44a28c5fb50906ebff145359" . --include="*.md" --include="*.ts"

Repository: DefiLlama/dimension-adapters

Length of output: 158


Document or validate the 100% LP ownership assumption.

The code assumes Olympus owns ~100% of the Camelot V2 LP (stated in the function docstring) and applies a fixed 0.25% fee rate to all swap inputs. However, there is no runtime validation of actual LP token ownership. If Olympus's share of the pool decreases, this calculation will overstate fees.

Add a comment clarifying this is a known constraint, or implement a check that queries the pool's LP token balance to scale fees accurately.

🤖 Prompt for AI Agents
In `@fees/olympus-dao.ts` around lines 436 - 454, The code assumes Olympus owns
~100% of the Camelot V2 LP but never validates that, so either document the
assumption or adjust fee calculation by scaling with actual LP ownership; update
the block using FEE_RATE, swapLogs, and fees.add to (a) add a clear comment near
FEE_RATE stating this is a hardcoded assumption and a TODO to validate
ownership, or (b) implement a runtime check that queries the pool for
totalSupply and Olympus LP token balance, compute ownershipShare =
olympusBalance / totalSupply and multiply fee0/fee1 by ownershipShare before
calling fees.add (use CHAIN_CONFIG.arbitrum addresses to identify tokens).
Ensure the chosen approach is clearly noted in comments and that any new async
lookup is performed before iterating swapLogs.

@treeoflife2 treeoflife2 self-assigned this Jan 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants