@@ -8,44 +8,98 @@ import {IATokenVault} from "./interfaces/IATokenVault.sol";
88import {IERC20 } from "@openzeppelin/token/ERC20/IERC20.sol " ;
99import {SafeERC20} from "@openzeppelin/token/ERC20/utils/SafeERC20.sol " ;
1010
11+ /**
12+ * @title ATokenVaultRevenueSplitterOwner
13+ * @author Aave Protocol
14+ * @notice ATokenVault owner with revenue split capabilities.
15+ */
1116contract ATokenVaultRevenueSplitterOwner is Ownable {
1217 using SafeERC20 for IERC20 ;
1318
19+ /**
20+ * @dev Emitted at construction time for each recipient set
21+ * @param recipient The address of the recipient set
22+ * @param shareInBps The recipient's share of the revenue in basis points
23+ */
1424 event RecipientSet (address indexed recipient , uint16 shareInBps );
1525
26+ /**
27+ * @dev Emitted when revenue is split for each recipient and asset
28+ * @param recipient The address of the recipient receiving the revenue
29+ * @param asset The asset being split
30+ * @param amount The amount of revenue sent to the recipient in the split asset
31+ */
1632 event RevenueSplit (address indexed recipient , address indexed asset , uint256 amount );
1733
18- uint256 public constant TOTAL_SHARE_IN_BPS = 10_000 ; // 100.00%
34+ /**
35+ * @dev The sum of all recipients' shares in basis points, represents 100.00%. Each basis point is 0.01%.
36+ */
37+ uint256 public constant TOTAL_SHARE_IN_BPS = 10_000 ;
1938
39+ /**
40+ * @dev The aToken Vault to own, whose revenue is split.
41+ */
2042 IATokenVault public immutable VAULT;
21-
43+
44+ /**
45+ * @dev A struct to represent a recipient and its share of the revenue in basis points.
46+ * @param addr The address of the recipient
47+ * @param shareInBps The recipient's share of the revenue in basis points
48+ */
2249 struct Recipient {
2350 address addr;
2451 uint16 shareInBps;
2552 }
2653
54+ /**
55+ * @dev The recipients set for this revenue splitter. Set at construction time only, cannot be modified afterwards.
56+ */
2757 Recipient[] internal _recipients;
2858
59+ /**
60+ * @dev Constructor.
61+ * @param vault The address of the aToken Vault to own, whose revenue is split.
62+ * @param owner The address owning this contract, the effective owner of the vault.
63+ * @param recipients The recipients to set for the revenue split. Cannot be modified afterwards.
64+ */
2965 constructor (address vault , address owner , Recipient[] memory recipients ) {
3066 VAULT = IATokenVault (vault);
3167 _setRecipients (recipients);
3268 _transferOwnership (owner);
3369 }
3470
35- function transferVaultOwnership (address newOwner ) public onlyOwner {
71+ /**
72+ * @dev Transfers the ownership of the aToken vault to a new owner. Claims all fees and rewards prior to transfer,
73+ * to secure already accrued fees and rewards for the configured split recipients.
74+ * @dev Only callable by the owner of this contract.
75+ * @dev DO NOT confuse with `transferOwnership` which transfers the ownership of this contract instead.
76+ * @param newVaultOwner The address of the new aToken vault owner.
77+ */
78+ function transferVaultOwnership (address newVaultOwner ) public onlyOwner {
3679 _claimRewards ();
3780 _withdrawFees ();
38- Ownable (address (VAULT)).transferOwnership (newOwner );
81+ Ownable (address (VAULT)).transferOwnership (newVaultOwner );
3982 }
4083
84+ /**
85+ * @dev Withdraws all vault fees to this contract, so they can be split among the configured recipients.
86+ */
4187 function withdrawFees () public {
4288 _withdrawFees ();
4389 }
4490
91+ /**
92+ * @dev Claims all vault rewards to this contract, so they can be split among the configured recipients.
93+ */
4594 function claimRewards () external {
4695 _claimRewards ();
4796 }
4897
98+ /**
99+ * @dev Splits the revenue from the given assets among the configured recipients. Assets must follow the ERC-20
100+ * interface and be held by this contract.
101+ * @param assets The assets to split the revenue from.
102+ */
49103 function splitRevenue (address [] calldata assets ) public {
50104 Recipient[] memory recipients = _recipients;
51105 for (uint256 i = 0 ; i < assets.length ; i++ ) {
@@ -60,8 +114,12 @@ contract ATokenVaultRevenueSplitterOwner is Ownable {
60114 }
61115 }
62116
117+ // TODO: Should we support splitting native currency revenue or only ERC20s?
63118 // TODO: address(0) used in the event instead of ad-hoc event for native revenue?
64119 // TODO: Should we assume recipients will succeed at receiving native? If one fails, the whole call fails.
120+ /**
121+ * @dev Splits the native currency revenue among the configured recipients.
122+ */
65123 function splitRevenue () public {
66124 uint256 amountToSplit = address (this ).balance;
67125 for (uint256 j = 0 ; j < _recipients.length ; j++ ) {
@@ -74,14 +132,33 @@ contract ATokenVaultRevenueSplitterOwner is Ownable {
74132 }
75133 }
76134
135+ /**
136+ * @dev Rescues assets that may have accidentally been transferred to the vault.
137+ * @dev Only callable by the owner of this contract.
138+ * @dev The asset to rescue cannot be the vault's aToken.
139+ * @dev Fees cannot be "rescued" as they are accrued in the vault's aToken. Rewards cannot be "rescued" as they are
140+ * not held by the vault contract. Thus, already accrued fees and rewards cannot be taken from split recipients.
141+ * @param asset The asset to rescue from the vault.
142+ * @param to The address to send the rescued assets to.
143+ * @param amount The amount of assets to rescue from the vault.
144+ */
77145 function emergencyRescue (address asset , address to , uint256 amount ) public onlyOwner {
78146 VAULT.emergencyRescue (asset, to, amount);
79147 }
80148
149+ /**
150+ * @dev Sets the fee for the vault.
151+ * @dev Only callable by the owner of this contract.
152+ * @param newFee The new fee for the vault.
153+ */
81154 function setFee (uint256 newFee ) public onlyOwner {
82155 VAULT.setFee (newFee);
83156 }
84157
158+ /**
159+ * @dev Getter for the revenue split configured recipients.
160+ * @return The configured recipients with their corresponding share in basis points.
161+ */
85162 function getRecipients () public view returns (Recipient[] memory ) {
86163 return _recipients;
87164 }
@@ -95,7 +172,9 @@ contract ATokenVaultRevenueSplitterOwner is Ownable {
95172 VAULT.withdrawFees (address (this ), feesToWithdraw);
96173 }
97174
98- // Assumes no duplicates
175+ /**
176+ * @dev Does not check for duplicates in the recipients array. Sum of shares must be represent 100.00% in BPS.
177+ */
99178 function _setRecipients (Recipient[] memory recipients ) internal {
100179 uint256 accumulatedShareInBps = 0 ;
101180 for (uint256 i = 0 ; i < recipients.length ; i++ ) {
0 commit comments