Skip to content

Commit c943e73

Browse files
committed
fix: account for subscription fee, resolve tests, param names
1 parent 16a5d59 commit c943e73

File tree

3 files changed

+35
-23
lines changed

3 files changed

+35
-23
lines changed

src/contracts/facilitators/gsm/converter/GsmConverter.sol

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -185,20 +185,20 @@ contract GsmConverter is Ownable, EIP712, IGsmConverter {
185185

186186
IGhoToken(GHO_TOKEN).transferFrom(originator, address(this), ghoAmount);
187187
IGhoToken(GHO_TOKEN).approve(address(GSM), ghoAmount);
188-
(uint256 issuedAssetAmount, uint256 ghoSold) = IGsm(GSM).buyAsset(minAmount, address(this));
188+
(uint256 boughtAssetAmount, uint256 ghoSold) = IGsm(GSM).buyAsset(minAmount, address(this));
189189
require(ghoAmount == ghoSold, 'INVALID_GHO_SOLD');
190190
IGhoToken(GHO_TOKEN).approve(address(GSM), 0);
191191

192-
IERC20(ISSUED_ASSET).approve(address(REDEMPTION_CONTRACT), issuedAssetAmount);
193-
IRedemption(REDEMPTION_CONTRACT).redeem(issuedAssetAmount);
194-
// redeemedAssetAmount matches issuedAssetAmount because Redemption exchanges in 1:1 ratio
192+
IERC20(ISSUED_ASSET).approve(address(REDEMPTION_CONTRACT), boughtAssetAmount);
193+
IRedemption(REDEMPTION_CONTRACT).redeem(boughtAssetAmount);
194+
// Redemption exchanges in 1:1 ratio between BUIDL and USDC
195195
require(
196196
IERC20(REDEEMED_ASSET).balanceOf(address(this)) ==
197-
initialRedeemedAssetBalance + issuedAssetAmount,
197+
initialRedeemedAssetBalance + boughtAssetAmount,
198198
'INVALID_REDEMPTION'
199199
);
200200
IERC20(ISSUED_ASSET).approve(address(REDEMPTION_CONTRACT), 0);
201-
IERC20(REDEEMED_ASSET).safeTransfer(receiver, issuedAssetAmount);
201+
IERC20(REDEEMED_ASSET).safeTransfer(receiver, boughtAssetAmount);
202202

203203
require(
204204
IGhoToken(GHO_TOKEN).balanceOf(address(this)) == initialGhoBalance,
@@ -209,8 +209,8 @@ contract GsmConverter is Ownable, EIP712, IGsmConverter {
209209
'INVALID_REMAINING_ISSUED_ASSET_BALANCE'
210210
);
211211

212-
emit BuyAssetThroughRedemption(originator, receiver, issuedAssetAmount, ghoSold);
213-
return (issuedAssetAmount, ghoSold);
212+
emit BuyAssetThroughRedemption(originator, receiver, boughtAssetAmount, ghoSold);
213+
return (boughtAssetAmount, ghoSold);
214214
}
215215

216216
/**
@@ -227,29 +227,37 @@ contract GsmConverter is Ownable, EIP712, IGsmConverter {
227227
address receiver
228228
) internal returns (uint256, uint256) {
229229
uint256 initialGhoBalance = IGhoToken(GHO_TOKEN).balanceOf(address(this));
230-
uint256 initialissuedAssetBalance = IERC20(ISSUED_ASSET).balanceOf(address(this));
230+
uint256 initialIssuedAssetBalance = IERC20(ISSUED_ASSET).balanceOf(address(this));
231231
uint256 initialRedeemedAssetBalance = IERC20(REDEEMED_ASSET).balanceOf(address(this));
232232

233-
(uint256 redeemedAssetAmount, , , ) = IGsm(GSM).getGhoAmountForSellAsset(maxAmount);
234-
IERC20(REDEEMED_ASSET).transferFrom(originator, address(this), redeemedAssetAmount);
235-
IERC20(REDEEMED_ASSET).approve(SUBSCRIPTION_CONTRACT, redeemedAssetAmount);
233+
(uint256 assetAmount, , , ) = IGsm(GSM).getGhoAmountForSellAsset(maxAmount); // asset is BUIDL
234+
IERC20(REDEEMED_ASSET).transferFrom(originator, address(this), assetAmount);
235+
IERC20(REDEEMED_ASSET).approve(SUBSCRIPTION_CONTRACT, assetAmount);
236236
//TODO: replace with proper issuance implementation later
237-
MockBUIDLSubscription(SUBSCRIPTION_CONTRACT).issuance(redeemedAssetAmount);
237+
MockBUIDLSubscription(SUBSCRIPTION_CONTRACT).issuance(assetAmount);
238+
uint256 subscribedAssetAmount = IERC20(ISSUED_ASSET).balanceOf(address(this)) -
239+
initialIssuedAssetBalance;
238240
// TODO: probably will be fees from issuance, so need to adjust the logic
241+
// only use this require only if preview of issuance is possible, otherwise it is redundant
239242
require(
240243
IERC20(ISSUED_ASSET).balanceOf(address(this)) ==
241-
initialissuedAssetBalance + redeemedAssetAmount,
244+
initialIssuedAssetBalance + subscribedAssetAmount,
242245
'INVALID_ISSUANCE'
243246
);
244247
// reset approval after issuance
245248
IERC20(REDEEMED_ASSET).approve(SUBSCRIPTION_CONTRACT, 0);
246249

247250
// TODO: account for fees for sellAsset amount param
248-
IERC20(ISSUED_ASSET).approve(GSM, redeemedAssetAmount);
249-
(uint256 assetAmount, uint256 ghoBought) = IGsm(GSM).sellAsset(maxAmount, receiver);
251+
(assetAmount, , , ) = IGsm(GSM).getGhoAmountForSellAsset(subscribedAssetAmount); // recalculate based on actual issuance amount, < maxAmount
252+
IERC20(ISSUED_ASSET).approve(GSM, assetAmount);
253+
(uint256 soldAssetAmount, uint256 ghoBought) = IGsm(GSM).sellAsset(
254+
subscribedAssetAmount,
255+
receiver
256+
);
250257
// reset approval after sellAsset
251258
IERC20(ISSUED_ASSET).approve(GSM, 0);
252259

260+
// by the end of the transaction, this contract should not retain any of the assets
253261
require(
254262
IGhoToken(GHO_TOKEN).balanceOf(address(this)) == initialGhoBalance,
255263
'INVALID_REMAINING_GHO_BALANCE'
@@ -258,8 +266,12 @@ contract GsmConverter is Ownable, EIP712, IGsmConverter {
258266
IERC20(REDEEMED_ASSET).balanceOf(address(this)) == initialRedeemedAssetBalance,
259267
'INVALID_REMAINING_REDEEMED_ASSET_BALANCE'
260268
);
269+
require(
270+
IERC20(ISSUED_ASSET).balanceOf(address(this)) == initialIssuedAssetBalance,
271+
'INVALID_REMAINING_ISSUED_ASSET_BALANCE'
272+
);
261273

262-
emit SellAssetThroughSubscription(originator, receiver, redeemedAssetAmount, ghoBought);
263-
return (assetAmount, ghoBought);
274+
emit SellAssetThroughSubscription(originator, receiver, soldAssetAmount, ghoBought);
275+
return (soldAssetAmount, ghoBought);
264276
}
265277
}

src/contracts/facilitators/gsm/converter/interfaces/IGsmConverter.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,27 @@ interface IGsmConverter {
1212
* @dev Emitted when a user buys an asset (selling GHO) in the GSM after a redemption
1313
* @param originator The address of the buyer originating the request
1414
* @param receiver The address of the receiver of the underlying asset
15-
* @param issuedAssetAmount The amount of the issued asset converted
15+
* @param boughtAssetAmount The amount of the asset bought
1616
* @param ghoAmount The amount of total GHO sold, inclusive of fee
1717
*/
1818
event BuyAssetThroughRedemption(
1919
address indexed originator,
2020
address indexed receiver,
21-
uint256 issuedAssetAmount,
21+
uint256 boughtAssetAmount,
2222
uint256 ghoAmount
2323
);
2424

2525
/**
2626
* @dev Emitted when a user sells an asset (buying GHO) in the GSM after an asset subscription
2727
* @param originator The address of the seller originating the request
2828
* @param receiver The address of the receiver of GHO
29-
* @param redeemedAssetAmount The amount of the redeemed asset converted
29+
* @param soldAssetAmount The amount of the asset sold
3030
* @param ghoAmount The amount of GHO bought, inclusive of fee
3131
*/
3232
event SellAssetThroughSubscription(
3333
address indexed originator,
3434
address indexed receiver,
35-
uint256 redeemedAssetAmount,
35+
uint256 soldAssetAmount,
3636
uint256 ghoAmount
3737
);
3838

src/test/TestGsmConverter.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ contract TestGsmConverter is TestGhoBase {
549549

550550
vm.startPrank(ALICE);
551551
USDC_TOKEN.approve(address(gsmConverter), DEFAULT_GSM_BUIDL_AMOUNT);
552-
vm.expectRevert('INVALID_ISSUANCE');
552+
vm.expectRevert('INVALID_AMOUNT');
553553
gsmConverter.sellAsset(DEFAULT_GSM_BUIDL_AMOUNT, ALICE);
554554
}
555555

0 commit comments

Comments
 (0)