Skip to content

Commit e06dbaa

Browse files
committed
fix: dividend external withdrawal
1 parent fe3c5b1 commit e06dbaa

File tree

5 files changed

+49
-16
lines changed

5 files changed

+49
-16
lines changed

src/facets/TokenizedVaultFacet.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,6 @@ contract TokenizedVaultFacet is Modifiers, ReentrancyGuard {
184184
// The _claimRebasingInterest method verifies the token is valid, and that there is available interest.
185185
// No need to do it again.
186186
LibTokenizedVault._claimRebasingInterest(_tokenId, _amount);
187-
LibTokenizedVault._payDividend(_guid, _tokenId, _tokenId, _tokenId, _amount);
187+
LibTokenizedVault._payDividend(_guid, LibAdmin._getSystemId(), _tokenId, _tokenId, _amount);
188188
}
189189
}

src/libs/LibTokenizedVault.sol

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,15 @@ library LibTokenizedVault {
246246
// issue dividend. if you are owed dividends on the _dividendTokenId, they will be collected
247247
// Check for possible infinite loop, but probably not
248248
_internalTransfer(_from, dividendBankId, _dividendTokenId, _amount);
249-
s.totalDividends[_to][_dividendTokenId] += _amount;
249+
uint256 tokenSupply = LibTokenizedVault._internalTokenSupply(_dividendTokenId);
250+
uint256 adjustedDividendAmount = _amount;
251+
if (_to == _dividendTokenId) {
252+
// withdrawn dividend was adjusted for the previous holder in this case,
253+
// therfore dividend amount should be increased in order to give existing token holders the correct amount
254+
adjustedDividendAmount = (_amount * (tokenSupply)) / (tokenSupply - _amount);
255+
}
256+
257+
s.totalDividends[_to][_dividendTokenId] += adjustedDividendAmount;
250258

251259
// keep track of the dividend denominations
252260
// if dividend has not yet been issued in this token, add it to the list and update mappings
@@ -305,7 +313,8 @@ library LibTokenizedVault {
305313

306314
address tokenAddress = LibHelpers._getAddressFromId(_tokenId);
307315

308-
uint256 depositTotal = s.depositTotal[_tokenId];
316+
// uint256 depositTotal = s.depositTotal[_tokenId];
317+
uint256 depositTotal = s.tokenSupply[_tokenId];
309318
uint256 total = LibERC20.balanceOf(tokenAddress, address(this));
310319

311320
// If the Nayms balance of the rebasing token has decreased and is lower than the deposit total, revert
@@ -318,7 +327,7 @@ library LibTokenizedVault {
318327
function _claimRebasingInterest(bytes32 _tokenId, uint256 _amount) internal {
319328
AppStorage storage s = LibAppStorage.diamondStorage();
320329

321-
if (s.depositTotal[_tokenId] == 0) {
330+
if (s.tokenSupply[_tokenId] == 0) {
322331
revert RebasingInterestNotInitialized(_tokenId);
323332
}
324333

@@ -327,7 +336,8 @@ library LibTokenizedVault {
327336
revert RebasingInterestInsufficient(_tokenId, _amount, accruedAmount);
328337
}
329338

330-
s.tokenBalances[_tokenId][_tokenId] += _amount;
331-
s.depositTotal[_tokenId] += _amount;
339+
// s.tokenBalances[_tokenId][_tokenId] += _amount;
340+
// s.depositTotal[_tokenId] += _amount;
341+
_internalMint(LibAdmin._getSystemId(), _tokenId, _amount);
332342
}
333343
}

src/libs/LibTokenizedVaultIO.sol

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ library LibTokenizedVaultIO {
3434
// Only mint what has been collected.
3535
LibTokenizedVault._internalMint(_receiverId, internalTokenId, mintAmount);
3636

37-
AppStorage storage s = LibAppStorage.diamondStorage();
38-
s.depositTotal[internalTokenId] += mintAmount;
39-
4037
// emit event
4138
emit ExternalDeposit(_receiverId, _externalTokenAddress, mintAmount);
4239
}
@@ -55,9 +52,6 @@ library LibTokenizedVaultIO {
5552
// transfer AFTER burn
5653
LibERC20.transfer(_externalTokenAddress, _receiver, _amount);
5754

58-
AppStorage storage s = LibAppStorage.diamondStorage();
59-
s.depositTotal[internalTokenId] -= _amount;
60-
6155
// emit event
6256
emit ExternalWithdraw(_entityId, _receiver, _externalTokenAddress, _amount);
6357
}

src/shared/AppStorage.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct AppStorage {
7979
mapping(string tokenSymbol => bytes32 objectId) tokenSymbolObjectId; // reverse mapping token symbol => object ID, to ensure symbol uniqueness
8080
mapping(bytes32 entityId => mapping(uint256 feeScheduleTypeId => FeeSchedule)) feeSchedules; // map entity ID to a fee schedule type and then to array of FeeReceivers (feeScheduleType (1-premium, 2-trading, n-others))
8181
mapping(bytes32 objectId => uint256 minimumSell) objectMinimumSell; // map object ID to minimum sell amount
82-
mapping(bytes32 objectId => uint256) depositTotal; // total amount deposited into contract, for rebasing tokens support
82+
mapping(bytes32 objectId => uint256) depositTotal; // note: DEPRECATED: total amount deposited into contract, for rebasing tokens support
8383
mapping(address userAddress => EntityApproval) selfOnboarding; // note: DEPRECATED
8484
/// Staking
8585
mapping(bytes32 entityId => StakingConfig) stakingConfigs; // StakingConfig for an entity

test/T03TokenizedVault.t.sol

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,20 +1186,24 @@ contract T03TokenizedVaultTest is D03ProtocolDefaults, MockAccounts {
11861186
changePrank(sm);
11871187
nayms.distributeAccruedInterest(wethId, 1 ether, makeId(LC.OBJECT_TYPE_DIVIDEND, bytes20("0x1")));
11881188

1189+
changePrank(david);
1190+
writeTokenBalance(david.addr, naymsAddress, wethAddress, 4 ether);
1191+
11891192
changePrank(alice.addr);
1190-
writeTokenBalance(alice.addr, naymsAddress, wethAddress, depositAmount);
1193+
writeTokenBalance(alice.addr, naymsAddress, wethAddress, 2 ether);
11911194
nayms.externalDeposit(wethAddress, 1 ether);
11921195
assertEq(nayms.internalBalanceOf(alice.entityId, wethId), 1 ether, "acc0EntityId wethId balance should INCREASE (mint)");
11931196

11941197
changePrank(bob.addr);
1195-
writeTokenBalance(bob.addr, naymsAddress, wethAddress, depositAmount);
1198+
writeTokenBalance(bob.addr, naymsAddress, wethAddress, 2 ether);
11961199
nayms.externalDeposit(wethAddress, 1 ether);
11971200
assertEq(nayms.internalBalanceOf(bob.entityId, wethId), 1 ether, "bobEntityId wethId balance should INCREASE (mint)");
11981201

11991202
vm.warp(2 weeks);
12001203

12011204
assertEq(nayms.accruedInterest(wethId), 0, "Accrued interest should be zero");
1202-
vm.mockCall(wethAddress, abi.encodeWithSelector(IERC20.balanceOf.selector), abi.encode(4 ether));
1205+
changePrank(david);
1206+
IERC20(wethAddress).transfer(naymsAddress, 2 ether);
12031207
assertEq(nayms.accruedInterest(wethId), 2 ether, "Accrued interest should increase");
12041208

12051209
changePrank(sm);
@@ -1217,6 +1221,31 @@ contract T03TokenizedVaultTest is D03ProtocolDefaults, MockAccounts {
12171221
nayms.withdrawDividend(bob.entityId, wethId, wethId);
12181222
assertEq(nayms.internalBalanceOf(bob.entityId, wethId), 2 ether, "Bob's wethId balance should INCREASE (mint)".red());
12191223
assertEq(nayms.getWithdrawableDividend(bob.entityId, wethId, wethId), 0, "bob's withdrawable divident should be zero".red());
1224+
1225+
vm.warp(4 weeks);
1226+
1227+
changePrank(david);
1228+
IERC20(wethAddress).transfer(naymsAddress, 2 ether);
1229+
assertEq(nayms.accruedInterest(wethId), 2 ether, "Accrued interest should increase");
1230+
1231+
changePrank(sm);
1232+
nayms.distributeAccruedInterest(wethId, 2 ether, makeId(LC.OBJECT_TYPE_DIVIDEND, bytes20("0x2")));
1233+
1234+
changePrank(alice.addr);
1235+
nayms.withdrawDividend(alice.entityId, wethId, wethId);
1236+
assertEq(nayms.internalBalanceOf(alice.entityId, wethId), 3 ether, "Alice's wethId balance should INCREASE (mint)".red());
1237+
assertEq(nayms.getWithdrawableDividend(alice.entityId, wethId, wethId), 0, "alice's withdrawable divident should be zero".red());
1238+
1239+
nayms.externalWithdrawFromEntity(alice.entityId, alice.addr, wethAddress, 3 ether);
1240+
assertEq(IERC20(wethAddress).balanceOf(alice.addr), 4 ether, "Alice's private balance should be increased".red());
1241+
1242+
changePrank(bob.addr);
1243+
nayms.withdrawDividend(bob.entityId, wethId, wethId);
1244+
assertEq(nayms.internalBalanceOf(bob.entityId, wethId), 3 ether, "Bob's wethId balance should INCREASE (mint)".red());
1245+
assertEq(nayms.getWithdrawableDividend(bob.entityId, wethId, wethId), 0, "Bob's withdrawable divident should be zero".red());
1246+
1247+
nayms.externalWithdrawFromEntity(bob.entityId, bob.addr, wethAddress, 3 ether);
1248+
assertEq(IERC20(wethAddress).balanceOf(bob.addr), 4 ether, "Bob's private balance should be increased".red());
12201249
}
12211250

12221251
// note withdrawAllDividends() will still succeed even if there are 0 dividends to be paid out,

0 commit comments

Comments
 (0)