Skip to content

Commit

Permalink
chore: clean up dependencies, remove USTB
Browse files Browse the repository at this point in the history
test: try to isolate rounding issues for USDC converter
  • Loading branch information
yan-man committed Nov 30, 2024
1 parent 9209e59 commit 8272ca6
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 61 deletions.
5 changes: 1 addition & 4 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,4 @@
url = https://github.com/aave/safety-module
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/ustb"]
path = lib/ustb
url = https://github.com/superstateinc/ustb
url = https://github.com/OpenZeppelin/openzeppelin-contracts
1 change: 0 additions & 1 deletion lib/ustb
Submodule ustb deleted from 394893
45 changes: 22 additions & 23 deletions src/contracts/facilitators/gsm/converter/USTBGsmConverter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,8 @@ contract USTBGsmConverter is Ownable, EIP712, IGsmConverter {
uint256 initialIssuedAssetBalance = IERC20(ISSUED_ASSET).balanceOf(address(this));
uint256 initialRedeemedAssetBalance = IERC20(REDEEMED_ASSET).balanceOf(address(this));

(uint256 minUSTBAmount, ) = ISubscriptionRedemption(REDEMPTION_CONTRACT).calculateUstbIn(
minAmount
);
// (uint256 minUSTBAmount, ) = ISubscription(REDEMPTION_CONTRACT).calculateUstbIn(minAmount);
uint256 minUSTBAmount = 0;

(, uint256 ghoAmount, , ) = IGsm(GSM).getGhoAmountForBuyAsset(minUSTBAmount);

Expand All @@ -196,21 +195,21 @@ contract USTBGsmConverter is Ownable, EIP712, IGsmConverter {
IGhoToken(GHO_TOKEN).approve(address(GSM), 0);

IERC20(ISSUED_ASSET).approve(address(REDEMPTION_CONTRACT), boughtAssetAmount);
ISubscriptionRedemption(REDEMPTION_CONTRACT).redeem(boughtAssetAmount);
IERC20(ISSUED_ASSET).approve(address(REDEMPTION_CONTRACT), 0);
IERC20(REDEEMED_ASSET).safeTransfer(receiver, minAmount);

require(
IGhoToken(GHO_TOKEN).balanceOf(address(this)) == initialGhoBalance,
'INVALID_REMAINING_GHO_BALANCE'
);
require(
IERC20(ISSUED_ASSET).balanceOf(address(this)) == initialIssuedAssetBalance,
'INVALID_REMAINING_ISSUED_ASSET_BALANCE'
);

emit BuyAssetThroughRedemption(originator, receiver, boughtAssetAmount, ghoSold);
return (boughtAssetAmount, ghoSold);
// ISubscription(REDEMPTION_CONTRACT).redeem(boughtAssetAmount);
// IERC20(ISSUED_ASSET).approve(address(REDEMPTION_CONTRACT), 0);
// IERC20(REDEEMED_ASSET).safeTransfer(receiver, minAmount);

// require(
// IGhoToken(GHO_TOKEN).balanceOf(address(this)) == initialGhoBalance,
// 'INVALID_REMAINING_GHO_BALANCE'
// );
// require(
// IERC20(ISSUED_ASSET).balanceOf(address(this)) == initialIssuedAssetBalance,
// 'INVALID_REMAINING_ISSUED_ASSET_BALANCE'
// );

// emit BuyAssetThroughRedemption(originator, receiver, boughtAssetAmount, ghoSold);
// return (boughtAssetAmount, ghoSold);
}

/**
Expand All @@ -230,15 +229,14 @@ contract USTBGsmConverter is Ownable, EIP712, IGsmConverter {
uint256 initialIssuedAssetBalance = IERC20(ISSUED_ASSET).balanceOf(address(this));
uint256 initialRedeemedAssetBalance = IERC20(REDEEMED_ASSET).balanceOf(address(this));

(uint256 redeemedAssetAmount, , , ) = IGsm(GSM).getGhoAmountForSellAsset(maxAmount); // asset is BUIDL
(uint256 redeemedAssetAmount, , , ) = IGsm(GSM).getGhoAmountForSellAsset(maxAmount); // asset is USTB
IERC20(REDEEMED_ASSET).transferFrom(originator, address(this), redeemedAssetAmount);
IERC20(REDEEMED_ASSET).approve(SUBSCRIPTION_CONTRACT, redeemedAssetAmount);

(uint256 subscribedAssetAmount, , ) = IERC20(SUBSCRIPTION_CONTRACT).calculateSuperstateTokenOut(
redeemedAssetAmount,
REDEEMED_ASSET
);
(uint256 subscribedAssetAmount, , ) = ISubscription(SUBSCRIPTION_CONTRACT)
.calculateSuperstateTokenOut(redeemedAssetAmount, REDEEMED_ASSET);
ISubscription(SUBSCRIPTION_CONTRACT).subscribe(redeemedAssetAmount, REDEEMED_ASSET);

require(
IERC20(ISSUED_ASSET).balanceOf(address(this)) ==
initialIssuedAssetBalance + subscribedAssetAmount,
Expand All @@ -249,6 +247,7 @@ contract USTBGsmConverter is Ownable, EIP712, IGsmConverter {

(redeemedAssetAmount, , , ) = IGsm(GSM).getGhoAmountForSellAsset(subscribedAssetAmount); // recalculate based on actual issuance amount, < maxAmount
IERC20(ISSUED_ASSET).approve(GSM, redeemedAssetAmount);

(uint256 soldAssetAmount, uint256 ghoBought) = IGsm(GSM).sellAsset(
subscribedAssetAmount,
receiver
Expand Down
16 changes: 14 additions & 2 deletions src/contracts/facilitators/gsm/dependencies/USTB/ISubscription.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,21 @@ pragma solidity ^0.8.10;

interface ISubscription {
/**
* @notice Subscribes an amount of USTB in exchange for USDC
* @param amount The amount of USDC to subscribe
* @notice The ```subscribe``` function takes in stablecoins and mints SuperstateToken in the proper amount for the msg.sender depending on the current Net Asset Value per Share.
* @param inAmount The amount of the stablecoin in
* @param stablecoin The address of the stablecoin to calculate with
*/
function subscribe(uint256 inAmount, address stablecoin) external;

function calculateSuperstateTokenOut(
uint256 inAmount,
address stablecoin
)
external
view
returns (
uint256 superstateTokenOutAmount,
uint256 stablecoinInAmountAfterFee,
uint256 feeOnStablecoinInAmount
);
}
31 changes: 29 additions & 2 deletions src/test/TestGhoBase.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import {IGhoCcipSteward} from '../contracts/misc/interfaces/IGhoCcipSteward.sol'
import {GhoCcipSteward} from '../contracts/misc/GhoCcipSteward.sol';
import {GhoBucketSteward} from '../contracts/misc/GhoBucketSteward.sol';
import {GsmConverter} from '../contracts/facilitators/gsm/converter/GsmConverter.sol';
import {USTBGsmConverter} from '../contracts/facilitators/gsm/converter/USTBGsmConverter.sol';

contract TestGhoBase is Test, Constants, Events {
using WadRayMath for uint256;
Expand Down Expand Up @@ -145,9 +146,12 @@ contract TestGhoBase is Test, Constants, Events {
Gsm GHO_GSM;
Gsm4626 GHO_GSM_4626;
Gsm GHO_BUIDL_GSM;
Gsm GHO_USTB_GSM;
GsmConverter GSM_CONVERTER;
USTBGsmConverter USTB_GSM_CONVERTER;
FixedPriceStrategy GHO_GSM_FIXED_PRICE_STRATEGY;
FixedPriceStrategy GHO_BUIDL_GSM_FIXED_PRICE_STRATEGY;
FixedPriceStrategy GHO_USTB_GSM_FIXED_PRICE_STRATEGY;
FixedPriceStrategy4626 GHO_GSM_4626_FIXED_PRICE_STRATEGY;
FixedFeeStrategy GHO_GSM_FIXED_FEE_STRATEGY;
SampleLiquidator GHO_GSM_LAST_RESORT_LIQUIDATOR;
Expand Down Expand Up @@ -295,7 +299,7 @@ contract TestGhoBase is Test, Constants, Events {
);
GHO_USTB_GSM_FIXED_PRICE_STRATEGY = new FixedPriceStrategy(
DEFAULT_FIXED_PRICE,
address(BUIDL_TOKEN),
address(USTB_TOKEN),
6
);
GHO_GSM_FIXED_FEE_STRATEGY = new FixedFeeStrategy(DEFAULT_GSM_BUY_FEE, DEFAULT_GSM_SELL_FEE);
Expand Down Expand Up @@ -334,10 +338,24 @@ contract TestGhoBase is Test, Constants, Events {
GHO_BUIDL_GSM = Gsm(address(buidlGsmProxy));
GHO_BUIDL_GSM.initialize(address(this), TREASURY, DEFAULT_GSM_BUIDL_EXPOSURE);

Gsm ustbGsm = new Gsm(
address(GHO_TOKEN),
address(USTB_TOKEN),
address(GHO_USTB_GSM_FIXED_PRICE_STRATEGY)
);
AdminUpgradeabilityProxy ustbGsmProxy = new AdminUpgradeabilityProxy(
address(ustbGsm),
SHORT_EXECUTOR,
''
);
GHO_USTB_GSM = Gsm(address(ustbGsmProxy));
GHO_USTB_GSM.initialize(address(this), TREASURY, DEFAULT_GSM_BUIDL_EXPOSURE);

GHO_GSM_FIXED_FEE_STRATEGY = new FixedFeeStrategy(DEFAULT_GSM_BUY_FEE, DEFAULT_GSM_SELL_FEE);
GHO_GSM.updateFeeStrategy(address(GHO_GSM_FIXED_FEE_STRATEGY));
GHO_GSM_4626.updateFeeStrategy(address(GHO_GSM_FIXED_FEE_STRATEGY));
GHO_BUIDL_GSM.updateFeeStrategy(address(GHO_GSM_FIXED_FEE_STRATEGY));
GHO_USTB_GSM.updateFeeStrategy(address(GHO_GSM_FIXED_FEE_STRATEGY));

GHO_GSM.grantRole(GSM_LIQUIDATOR_ROLE, address(GHO_GSM_LAST_RESORT_LIQUIDATOR));
GHO_GSM.grantRole(GSM_SWAP_FREEZER_ROLE, address(GHO_GSM_SWAP_FREEZER));
Expand Down Expand Up @@ -435,7 +453,16 @@ contract TestGhoBase is Test, Constants, Events {
address(USDC_TOKEN)
);

USTB_SUBCRIPTION = new MockUSTBSubscription(address(USDC_TOKEN), address(USDC_TOKEN));
// USTB
USTB_SUBCRIPTION = new MockUSTBSubscription(address(USTB_TOKEN), address(USDC_TOKEN), 1e8);
USTB_GSM_CONVERTER = new USTBGsmConverter(
address(this),
address(GHO_USTB_GSM),
address(BUIDL_USDC_REDEMPTION),
address(USTB_SUBCRIPTION),
address(USTB_TOKEN),
address(USDC_TOKEN)
);
}

function ghoFaucet(address to, uint256 amount) public {
Expand Down
53 changes: 27 additions & 26 deletions src/test/TestUSTBGsmConverterEdge.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import './TestGhoBase.t.sol';

contract TestGsmConverterEdge is TestGhoBase {
function setUp() public {
setUSTBPrice(1_100_000_000);
USTB_SUBCRIPTION.setUSTBPrice(9.5e8);
}

/// @dev test buyAsset with zero fee to simulate errors seen by TokenLogic
Expand All @@ -17,7 +17,7 @@ contract TestGsmConverterEdge is TestGhoBase {
// Left: 99_999_999_000_000_000_000
// Right: 100_000_000_000_000_000_000
function testSellAssetZeroFee_roundingError() public {
GHO_BUIDL_GSM.updateFeeStrategy(address(0));
GHO_USTB_GSM.updateFeeStrategy(address(0));

// Alice sells USDC for GHO
// - GSM converter swaps USDC for BUIDL
Expand All @@ -28,34 +28,35 @@ contract TestGsmConverterEdge is TestGhoBase {

console2.log('GHO_TOKEN.balanceOf(ALICE) %e', GHO_TOKEN.balanceOf(ALICE));

// vm.startPrank(FAUCET);
// // Supply BUIDL to issuance contract
// BUIDL_TOKEN.mint(address(BUIDL_USDC_ISSUANCE), DEFAULT_GSM_USDC_AMOUNT);
// vm.stopPrank();
vm.startPrank(FAUCET);
// Supply USTB to issuance contract
USTB_TOKEN.mint(address(USTB_SUBCRIPTION), DEFAULT_GSM_USDC_AMOUNT * 100);
vm.stopPrank();

// vm.startPrank(ALICE);
// USDC_TOKEN.approve(address(GSM_CONVERTER), DEFAULT_GSM_USDC_AMOUNT);
vm.startPrank(ALICE);
USTB_TOKEN.approve(address(USTB_GSM_CONVERTER), DEFAULT_GSM_USDC_AMOUNT * 100);
USDC_TOKEN.approve(address(USTB_GSM_CONVERTER), DEFAULT_GSM_USDC_AMOUNT);

// console2.log(
// 'BUIDL_TOKEN.balanceOf(address(GHO_BUIDL_GSM)) %e',
// BUIDL_TOKEN.balanceOf(address(GHO_BUIDL_GSM))
// );
console2.log(
'USTB_TOKEN.balanceOf(address(GHO_USTB_GSM)) %e',
USTB_TOKEN.balanceOf(address(GHO_USTB_GSM))
);

// (uint256 assetAmount, uint256 ghoBought) = GSM_CONVERTER.sellAsset(
// DEFAULT_GSM_USDC_AMOUNT,
// ALICE
// );
// vm.stopPrank();
(uint256 assetAmount, uint256 ghoBought) = USTB_GSM_CONVERTER.sellAsset(
DEFAULT_GSM_USDC_AMOUNT,
ALICE
);
vm.stopPrank();

// console2.log('------after sellAsset------');
// console2.log('calculated assetAmount %e', assetAmount);
// console2.log('calculated ghoBought %e', ghoBought);
// console2.log('GHO_TOKEN.balanceOf(ALICE) %e', GHO_TOKEN.balanceOf(ALICE));
// console2.log('DEFAULT_GSM_GHO_AMOUNT %e', DEFAULT_GSM_GHO_AMOUNT);
// console2.log(
// 'BUIDL_TOKEN.balanceOf(address(GHO_BUIDL_GSM)) %e',
// BUIDL_TOKEN.balanceOf(address(GHO_BUIDL_GSM))
// );
console2.log('------after sellAsset------');
console2.log('calculated assetAmount %e', assetAmount);
console2.log('calculated ghoBought %e', ghoBought);
console2.log('GHO_TOKEN.balanceOf(ALICE) %e', GHO_TOKEN.balanceOf(ALICE));
console2.log('DEFAULT_GSM_GHO_AMOUNT %e', DEFAULT_GSM_GHO_AMOUNT);
console2.log(
'USTB_TOKEN.balanceOf(address(GHO_USTB_GSM)) %e',
USTB_TOKEN.balanceOf(address(GHO_USTB_GSM))
);

// assertEq(GHO_TOKEN.balanceOf(ALICE), DEFAULT_GSM_GHO_AMOUNT, 'Unexpected final GHO balance');
}
Expand Down
4 changes: 1 addition & 3 deletions src/test/mocks/MockUSTBSubscription.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,10 @@ contract MockUSTBSubscription {
uint256 feeOnStablecoinInAmount
)
{
StablecoinConfig memory config = supportedStablecoins[stablecoin];

feeOnStablecoinInAmount = 0;
stablecoinInAmountAfterFee = inAmount - feeOnStablecoinInAmount;

usdPerSuperstateTokenChainlinkRaw = USTBPrice; // 9.5 USDC/SUPERSTATE_TOKEN
uint256 usdPerSuperstateTokenChainlinkRaw = USTBPrice; // 9.5 USDC/SUPERSTATE_TOKEN

uint256 stablecoinPrecision = 10 ** 6;
uint256 chainlinkFeedPrecision = 10 ** 8;
Expand Down

0 comments on commit 8272ca6

Please sign in to comment.