Skip to content

Commit 18fd8c1

Browse files
Revert per-user transfer re-attribution; remove _update override
Why: - Transfers no longer re-attribute underlying shares; we will update flows and asset mappings only on deposit/withdraw/redeem per the corrected docs - Remove per-user active vault tracking used only for re-attribution Test plan: - Compile
1 parent 86ed748 commit 18fd8c1

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

contracts/rewards/SendEarnRewards.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ contract SendEarnRewards is ERC4626, AccessControl, ReentrancyGuard {
4242
address[] private _activeVaults;
4343
mapping(address => bool) private _isActiveVault;
4444

45+
4546
event Deposited(address indexed user, address indexed vault, uint256 assetsIn, uint256 underlyingSharesReceived);
4647
event Withdrawn(address indexed user, address indexed vault, uint256 assetsOut, uint256 underlyingSharesRedeemed);
4748

@@ -78,7 +79,6 @@ contract SendEarnRewards is ERC4626, AccessControl, ReentrancyGuard {
7879
}
7980

8081
// Accounting: sum across tracked SendEarn vaults (view-only) for totalAssets.
81-
// Note: conversions remain 1:1 for simplicity while streaming is deferred.
8282
function totalAssets() public view override returns (uint256 assets) {
8383
uint256 n = _activeVaults.length;
8484
for (uint256 i = 0; i < n; i++) {
@@ -147,4 +147,5 @@ contract SendEarnRewards is ERC4626, AccessControl, ReentrancyGuard {
147147
require(factory.isSendEarn(v), "not SendEarn");
148148
require(IERC4626(v).asset() == address(asset()), "asset mismatch");
149149
}
150+
150151
}

docs/rewards-aggregator-erc4626.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,56 @@ All routed targets MUST satisfy:
5959
- `assets += IERC4626(v).convertToAssets(IERC4626(v).balanceOf(address(this)))`
6060
- This is a view-only iteration. State-changing flows remain single-vault without loops.
6161

62+
## CFA streaming integration (v2.1) — Superfluid “flow” helper
63+
Status: planned in v2.1 (docs-first; implementation next).
64+
65+
Goal
66+
- Stream SENDx (SuperToken) per user at a rate proportional to their current value in the aggregator.
67+
- Use Superfluid’s SuperTokenV1Library `flow(ISuperToken token, address receiver, int96 rate)` helper to create/update/delete flows.
68+
69+
Key concepts
70+
- Token: `sendx` (constructor arg), an ISuperToken. The aggregator must be pre-funded with SENDx to cover the flow buffer.
71+
- Triggers: Recompute a user’s flow after each state-changing event that affects the user’s value:
72+
- deposit(receiver)
73+
- withdraw(owner)
74+
- transfer(from→to): recompute for both parties after proportional re-attribution
75+
- Value basis (per user): sum across the user’s active vaults of `convertToAssets(_userUnderlyingShares[user][vault])`.
76+
- Policy params:
77+
- `annualRateBps`: annualized rate in basis points (e.g., 300 = 3%)
78+
- `secondsPerYear`: denominator to convert annual to per-second
79+
- `exchangeRateWad`: asset→SENDx conversion (fixed-point); default 1e18 for 1:1
80+
- Flow math (per second):
81+
- `perSecond = floor( (sumAssets * exchangeRateWad) * annualRateBps / 10_000 / secondsPerYear / 1e18 )`
82+
- Use `int96` cast; if perSecond==0, call `flow(token, user, 0)` to delete.
83+
84+
Integration outline (pseudocode)
85+
- Import library: `using SuperTokenV1Library for ISuperToken;`
86+
- After event, recompute and set flow:
87+
```
88+
function _updateFlow(address user) internal {
89+
uint256 assets = 0;
90+
for (address v in _userActiveVaults[user]) {
91+
uint256 uShares = _userUnderlyingShares[user][v];
92+
if (uShares == 0) continue;
93+
assets += IERC4626(v).convertToAssets(uShares);
94+
}
95+
uint256 wad = assets * exchangeRateWad;
96+
uint256 annual = wad * annualRateBps / 10_000;
97+
uint256 perSec = annual / secondsPerYear / 1e18;
98+
int96 rate = int96(int256(perSec));
99+
sendx.flow(user, rate); // create/update/delete as needed
100+
}
101+
```
102+
103+
Operational notes
104+
- Pre-fund with SENDx to satisfy CFA buffer or the flow creation will revert.
105+
- Flows are per-user, from the aggregator to the user.
106+
- If you change `annualRateBps`/`exchangeRateWad`, you may optionally batch-recompute flows for a set of users (future helper).
107+
108+
References
109+
- SuperTokenV1Library: https://github.com/superfluid-finance/protocol-monorepo/blob/dev/packages/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol
110+
- CFA docs: https://docs.superfluid.finance/superfluid/developers/constant-flow-agreement-cfa
111+
62112
## Transferability
63113
- Aggregator shares follow normal ERC20 semantics: transfers are allowed. The aggregator does not maintain per‑user vault ledgers.
64114

0 commit comments

Comments
 (0)