Skip to content

Commit

Permalink
feat: add fractional redeem collection
Browse files Browse the repository at this point in the history
  • Loading branch information
rndquu committed Apr 5, 2024
1 parent 8b3bfb1 commit a9cd4a6
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 15 deletions.
6 changes: 5 additions & 1 deletion packages/contracts/src/dollar/facets/UbiquityPoolFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,11 @@ contract UbiquityPoolFacet is IUbiquityPool, Modifiers {
/// @inheritdoc IUbiquityPool
function collectRedemption(
uint256 collateralIndex
) external nonReentrant returns (uint256 collateralAmount) {
)
external
nonReentrant
returns (uint256 governanceAmount, uint256 collateralAmount)
{
return LibUbiquityPool.collectRedemption(collateralIndex);
}

Expand Down
3 changes: 2 additions & 1 deletion packages/contracts/src/dollar/interfaces/IUbiquityPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,12 @@ interface IUbiquityPool {
* @dev 2. `collectRedemption()`
* @dev This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block
* @param collateralIndex Collateral token index being collected
* @return governanceAmount Amount of Governance tokens redeemed
* @return collateralAmount Amount of collateral tokens redeemed
*/
function collectRedemption(
uint256 collateralIndex
) external returns (uint256 collateralAmount);
) external returns (uint256 governanceAmount, uint256 collateralAmount);

/**
* @notice Updates collateral token price in USD from ChainLink price feed
Expand Down
21 changes: 18 additions & 3 deletions packages/contracts/src/dollar/libraries/LibUbiquityPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -698,20 +698,21 @@ library LibUbiquityPool {
}

/**
* @notice Used to collect collateral tokens after redeeming/burning Ubiquity Dollars
* @notice Used to collect collateral and Governance tokens after redeeming/burning Ubiquity Dollars
* @dev Redeem process is split in two steps:
* @dev 1. `redeemDollar()`
* @dev 2. `collectRedemption()`
* @dev This is done in order to prevent someone using a flash loan of a collateral token to mint, redeem, and collect in a single transaction/block
* @param collateralIndex Collateral token index being collected
* @return governanceAmount Amount of Governance tokens redeemed
* @return collateralAmount Amount of collateral tokens redeemed
*/
function collectRedemption(
uint256 collateralIndex
)
internal
collateralEnabled(collateralIndex)
returns (uint256 collateralAmount)
returns (uint256 governanceAmount, uint256 collateralAmount)
{
UbiquityPoolStorage storage poolStorage = ubiquityPoolStorage();

Expand All @@ -728,8 +729,18 @@ library LibUbiquityPool {
"Too soon to collect redemption"
);

bool sendGovernance = false;
bool sendCollateral = false;

if (poolStorage.redeemGovernanceBalances[msg.sender] > 0) {
governanceAmount = poolStorage.redeemGovernanceBalances[msg.sender];
poolStorage.redeemGovernanceBalances[msg.sender] = 0;
poolStorage.unclaimedPoolGovernance = poolStorage
.unclaimedPoolGovernance
.sub(governanceAmount);
sendGovernance = true;
}

if (
poolStorage.redeemCollateralBalances[msg.sender][collateralIndex] >
0
Expand All @@ -746,7 +757,11 @@ library LibUbiquityPool {
sendCollateral = true;
}

// send out the tokens
// send out tokens
if (sendGovernance) {
IERC20(LibAppStorage.appStorage().governanceTokenAddress)
.safeTransfer(msg.sender, governanceAmount);
}
if (sendCollateral) {
IERC20(poolStorage.collateralAddresses[collateralIndex])
.safeTransfer(msg.sender, collateralAmount);
Expand Down
33 changes: 23 additions & 10 deletions packages/contracts/test/diamond/facets/UbiquityPoolFacet.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1011,18 +1011,22 @@ contract UbiquityPoolFacetTest is DiamondTestSetup {
1000000 // redeem threshold
);

// user sends 100 collateral tokens and gets 99 Dollars (-1% mint fee)
// admin sets collateral ratio to 95%
vm.prank(admin);
ubiquityPoolFacet.setCollateralRatio(950_000);

// user burns 50 Governance tokens (worth $0.1) + 95 collateral tokens and gets 99 Dollars (-1% mint fee)
vm.prank(user);
ubiquityPoolFacet.mintDollar(
0, // collateral index
100e18, // Dollar amount
99e18, // min amount of Dollars to mint
100e18, // max collateral to send
0, // max Governance tokens to send
1100e18, // max Governance tokens to send
false // force 1-to-1 mint (i.e. provide only collateral without Governance tokens)
);

// user redeems 99 Dollars for collateral
// user redeems 99 Dollars for collateral and Governance tokens
vm.prank(user);
ubiquityPoolFacet.redeemDollar(
0, // collateral index
Expand All @@ -1035,19 +1039,28 @@ contract UbiquityPoolFacetTest is DiamondTestSetup {
vm.roll(block.number + 3);

// balances before
assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 100e18);
assertEq(collateralToken.balanceOf(user), 0);
assertEq(collateralToken.balanceOf(address(ubiquityPoolFacet)), 95e18);
assertEq(collateralToken.balanceOf(user), 5e18);
assertEq(
governanceToken.balanceOf(address(ubiquityPoolFacet)),
48510485104851048510
); // ~48
assertEq(governanceToken.balanceOf(user), 1949999499994999950000); // ~1950

vm.prank(user);
uint256 collateralAmount = ubiquityPoolFacet.collectRedemption(0);
assertEq(collateralAmount, 97.02e18); // $99 - 2% redemption fee
(uint256 governanceAmount, uint256 collateralAmount) = ubiquityPoolFacet
.collectRedemption(0);
assertEq(governanceAmount, 48510485104851048510); // ~48
assertEq(collateralAmount, 92169000000000000000); // ~92 = $95 - 2% redemption fee

// balances after
assertEq(
collateralToken.balanceOf(address(ubiquityPoolFacet)),
2.98e18
);
assertEq(collateralToken.balanceOf(user), 97.02e18);
2.831 ether
); // redemption fee left in the pool
assertEq(collateralToken.balanceOf(user), 97.169 ether);
assertEq(governanceToken.balanceOf(address(ubiquityPoolFacet)), 0);
assertEq(governanceToken.balanceOf(user), 1998509985099850998510); // ~1998
}

function testCollectRedemption_ShouldRevert_IfCollateralDisabled() public {
Expand Down

0 comments on commit a9cd4a6

Please sign in to comment.