Skip to content

Commit

Permalink
test(pool-facet-handler): add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandr-masl committed Sep 2, 2024
1 parent fd8acb6 commit 26abd14
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 68 deletions.
175 changes: 116 additions & 59 deletions packages/contracts/test/invariant/diamond/facets/PoolFacetHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,31 @@ import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
contract PoolFacetHandler is Test {
using SafeMath for uint256;

// mock three ChainLink price feeds, one for each token
MockChainLinkFeed collateralTokenPriceFeed;
MockChainLinkFeed stableUsdPriceFeed;
MockChainLinkFeed ethUsdPriceFeed;

UbiquityPoolFacet ubiquityPoolFacet;

// mock two users
address admin;
address user;
MockCurveStableSwapNG curveDollarPlainPool;

event MintSuccess(uint256 dollarAmount);
event MintFailed(bytes reason);

event redeemSuccess(uint256 dollarAmount);
event redeemFailed(bytes reason);
// mock curve pool Stablecoin/Dollar
MockCurveStableSwapNG curveDollarPlainPool;

/**
* @notice Constructs the PoolFacetHandler contract by initializing the necessary mocked contracts and addresses.
* @dev This constructor sets up the initial state with provided mock price feeds, pool facet, and user addresses.
* @param _collateralTokenPriceFeed The mock price feed for collateral tokens.
* @param _stableUsdPriceFeed The mock price feed for USD stablecoin.
* @param _ethUsdPriceFeed The mock price feed for ETH/USD.
* @param _ubiquityPoolFacet The pool facet contract responsible for managing Ubiquity Dollars.
* @param _admin The address with admin privileges, used for administrative actions in the pool.
* @param _user The user address that interacts with the pool for testing purposes.
* @param _curveDollarPlainPool The mocked Curve pool contract used for dollar-based operations.
*/
constructor(
MockChainLinkFeed _collateralTokenPriceFeed,
MockChainLinkFeed _stableUsdPriceFeed,
Expand All @@ -43,8 +54,12 @@ contract PoolFacetHandler is Test {
curveDollarPlainPool = _curveDollarPlainPool;
}

// Dollar price manipulations
//========================
/**
* @notice Manipulates the Ubiquity Dollar price to a value above a set threshold.
* @dev This function assumes the new dollar price is within the specified range (greater than 1e18 and less than 2e18).
* It then updates the mocked Curve pool parameters and adjusts the collateral ratio in the UbiquityPoolFacet.
* @param newDollarPrice The new price for Ubiquity Dollar, expected to be within the range of 1e18 to 2e18.
*/
function setDollarPriceAboveThreshold(uint256 newDollarPrice) public {
vm.assume(newDollarPrice > 1e18 && newDollarPrice < 2e18);

Expand All @@ -57,6 +72,12 @@ contract PoolFacetHandler is Test {
ubiquityPoolFacet.setCollateralRatio(newCollateralRatio);
}

/**
* @notice Manipulates the Ubiquity Dollar price to a value below a set threshold.
* @dev This function assumes the new dollar price is within the specified range (greater than or equal to 0.5e18 and less than 1e18).
* It then updates the mocked Curve pool parameters and adjusts the collateral ratio in the UbiquityPoolFacet accordingly.
* @param newDollarPrice The new price for Ubiquity Dollar, expected to be within the range of 0.5e18 to 1e18.
*/
function setDollarPriceBelowThreshold(uint256 newDollarPrice) public {
vm.assume(newDollarPrice >= 0.5e18 && newDollarPrice < 1e18);

Expand All @@ -69,13 +90,25 @@ contract PoolFacetHandler is Test {
ubiquityPoolFacet.setCollateralRatio(newCollateralRatio);
}

// Redeem manipulations
//========================
/**
* @notice Manipulates the redemption delay in blocks for UbiquityPoolFacet.
* @dev This function allows the admin to set a delay in blocks before a redemption can be completed.
* It assumes the caller is the admin and pranks the transaction as the admin to set the redemption delay.
* @param delay The number of blocks to set as the redemption delay.
*/
function setRedemptionDelay(uint256 delay) public {
vm.prank(admin);
ubiquityPoolFacet.setRedemptionDelayBlocks(delay);
}

/**
* @notice Manipulates the minting and redemption fees for UbiquityPoolFacet.
* @dev This function allows the admin to set the fees for minting and redeeming tokens in the pool.
* It assumes the caller is the admin and pranks the transaction as the admin to set the fees.
* The function also ensures that the provided mint and redeem fees fall within the acceptable range.
* @param mintFee The fee to be set for minting, expressed in basis points (1/100 of a percent).
* @param redeemFee The fee to be set for redeeming, expressed in basis points (1/100 of a percent).
*/
function setMintAndRedeemFees(uint256 mintFee, uint256 redeemFee) public {
vm.assume(mintFee >= 100000 && mintFee <= 200000);
vm.assume(redeemFee >= 100000 && redeemFee <= 200000);
Expand All @@ -88,39 +121,25 @@ contract PoolFacetHandler is Test {
ubiquityPoolFacet.collectRedemption(0);
}

function redeemDollar(
uint256 _dollarAmount,
uint256 _governanceOutMin,
uint256 _collateralOutMin
) public {
vm.assume(_dollarAmount > 0 && _dollarAmount < type(uint256).max / 2);
vm.assume(_governanceOutMin >= 0 && _governanceOutMin <= _dollarAmount);
vm.assume(_collateralOutMin >= 0 && _collateralOutMin <= _dollarAmount);

vm.prank(user);
try
ubiquityPoolFacet.redeemDollar(
0,
_dollarAmount,
_governanceOutMin,
_collateralOutMin
)
{
emit redeemSuccess(_dollarAmount);
} catch (bytes memory reason) {
emit redeemFailed(reason);
}
}

// Ceiling manipulations
//========================
/**
* @notice Manipulates the pool ceiling for UbiquityPoolFacet.
* @dev This function allows the admin to set a new ceiling for the pool, which determines the maximum
* amount of collateral that can be utilized in the pool. The function assumes the caller is the admin
* and pranks the transaction as the admin to set the new ceiling.
* @param newCeiling The new ceiling value to be set for the pool, representing the maximum amount
* of collateral in the pool.
*/
function setPoolCeiling(uint256 newCeiling) public {
vm.prank(admin);
ubiquityPoolFacet.setPoolCeiling(0, newCeiling);
}

// Collateral price manipulations
//========================
/**
* @notice Manipulates the collateral price and updates the corresponding collateral ratio.
* @dev This function adjusts the price of the collateral token using a mock ChainLink price feed.
* It assumes the new price is within the allowed range and updates the collateral ratio in the UbiquityPoolFacet.
* @param _newPrice The new price of the collateral, scaled by 1e8 (e.g., a price of $1 is represented as 1e8).
*/
function setCollateralPrice(int256 _newPrice) public {
vm.assume(_newPrice >= 50_000_000 && _newPrice <= 200_000_000);

Expand All @@ -138,8 +157,12 @@ contract PoolFacetHandler is Test {
ubiquityPoolFacet.setCollateralRatio(newCollateralRatio);
}

// USD stablecoin price manipulations
//========================
/**
* @notice Manipulates the stable USD price and updates the corresponding collateral ratio.
* @dev This function adjusts the price of the stable USD token using a mock ChainLink price feed.
* It assumes the new price is within the specified range and updates the collateral ratio in the UbiquityPoolFacet.
* @param _newPrice The new price of the stable USD token, scaled by 1e8 (e.g., a price of $1 is represented as 1e8).
*/
function setStableUsdPrice(uint256 _newPrice) public {
vm.assume(_newPrice >= 0.5e8 && _newPrice <= 1.5e8); // Assume a range for testing

Expand All @@ -155,8 +178,12 @@ contract PoolFacetHandler is Test {
ubiquityPoolFacet.setCollateralRatio(newCollateralRatio);
}

// ETH/USD price manipulations
//========================
/**
* @notice Manipulates the ETH/USD price using a mock ChainLink price feed.
* @dev This function assumes the new price is within the specified range and updates the ETH/USD price
* in the corresponding mock price feed.
* @param _newPrice The new ETH/USD price, scaled by 1e8 (e.g., a price of $1,000 is represented as 1000e8).
*/
function setEthUsdPrice(uint256 _newPrice) public {
vm.assume(_newPrice >= 1000e8 && _newPrice <= 5000e8);

Expand All @@ -169,36 +196,66 @@ contract PoolFacetHandler is Test {
);
}

/**
* @notice Mints Ubiquity Dollar tokens using specified collateral and governance token inputs.
* @dev Assumes that the dollar amount is within a safe range, the minimum dollar output is less than or equal to the input amount,
* and the collateral and governance inputs are valid. The function then pranks the specified user to simulate a mint transaction.
* @param _dollarAmount The amount of Ubiquity Dollars to mint.
* @param _dollarOutMin The minimum amount of Ubiquity Dollars expected to be received from the minting process.
* @param _maxCollateralIn The maximum amount of collateral tokens to use for minting.
* @param _maxGovernanceIn The maximum amount of governance tokens to use for minting.
* @param _isOneToOne A boolean flag indicating whether the minting process should be executed on a one-to-one basis with the collateral.
*/
function mintUbiquityDollars(
uint256 _dollarAmount,
uint256 _dollarOutMin,
uint256 _maxCollateralIn,
uint256 _maxGovernanceIn,
bool _isOneToOne
) public {
vm.assume(_dollarAmount > 0 && _dollarAmount < type(uint256).max / 2);
vm.assume(
_dollarAmount > 0 && _dollarAmount < type(uint256).max.div(2)
);
vm.assume(_dollarOutMin <= _dollarAmount);
vm.assume(
_maxCollateralIn > 0 && _maxCollateralIn < type(uint256).max / 2
_maxCollateralIn > 0 && _maxCollateralIn < type(uint256).max.div(2)
);
vm.assume(
_maxGovernanceIn >= 0 && _maxGovernanceIn < type(uint256).max.div(2)
);

vm.prank(user);

ubiquityPoolFacet.mintDollar(
0,
_dollarAmount,
_dollarOutMin,
_maxCollateralIn,
_maxGovernanceIn,
_isOneToOne
);
}

/**
* @notice Redeems Ubiquity Dollar tokens for collateral and governance tokens.
* @dev Assumes the dollar amount is within a safe range, and that the minimum expected governance and collateral outputs are valid.
* The function then pranks the specified user to simulate a redemption transaction.
* @param _dollarAmount The amount of Ubiquity Dollars to redeem.
* @param _governanceOutMin The minimum amount of governance tokens expected to be received from the redemption process.
* @param _collateralOutMin The minimum amount of collateral tokens expected to be received from the redemption process.
*/
function redeemDollar(
uint256 _dollarAmount,
uint256 _governanceOutMin,
uint256 _collateralOutMin
) public {
vm.assume(
_maxGovernanceIn >= 0 && _maxGovernanceIn < type(uint256).max / 2
_dollarAmount > 0 && _dollarAmount < type(uint256).max.div(2)
);
vm.assume(_governanceOutMin >= 0 && _governanceOutMin <= _dollarAmount);
vm.assume(_collateralOutMin >= 0 && _collateralOutMin <= _dollarAmount);

vm.prank(user);
try
ubiquityPoolFacet.mintDollar(
0,
_dollarAmount,
_dollarOutMin,
_maxCollateralIn,
_maxGovernanceIn,
_isOneToOne
)
{
emit MintSuccess(_dollarAmount);
} catch (bytes memory reason) {
emit MintFailed(reason);
}
ubiquityPoolFacet.redeemDollar(0, 0.1e18, 0, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,28 +163,25 @@ contract UbiquityPoolFacetInvariantTest is DiamondTestSetup {
targetContract(address(handler));
}

/**
* @notice Ensures that the total supply of Ubiquity Dollars does not exceed the collateral value backing them.
* @dev This invariant checker calculates the total supply of Ubiquity Dollars in USD terms and compares it to the USD value of the collateral.
* The invariant asserts that the value of minted dollars does not exceed the value of the collateral.
* If the invariant is violated, it indicates that more Ubiquity Dollars have been minted than the available collateral can support.
*/
function invariant_CannotMintMoreDollarsThanCollateral() public {
uint256 totalDollarSupply = IERC20Ubiquity(
managerFacet.dollarTokenAddress()
).totalSupply();

uint256 collateralUsdBalance = ubiquityPoolFacet.collateralUsdBalance();
console.log(
":::::::| UbiquityPoolFacetInvariantTest | collateralUsdBalance:",
collateralUsdBalance
);

vm.assume(collateralUsdBalance > 0 && totalDollarSupply > 0);

uint256 dollarPrice = ubiquityPoolFacet.getDollarPriceUsd();
uint256 totalDollarSupplyInUsd = (totalDollarSupply * dollarPrice) /
1e6;

console.log(
":::::::| UbiquityPoolFacetInvariantTest11 | totalDollarSupplyInUsd:",
totalDollarSupplyInUsd
);

assertTrue(
totalDollarSupplyInUsd <= collateralUsdBalance,
"Minted dollars exceed collateral value"
Expand Down

0 comments on commit 26abd14

Please sign in to comment.