Skip to content

Commit

Permalink
feat: tests passing
Browse files Browse the repository at this point in the history
  • Loading branch information
lucas-manuel committed Jul 3, 2024
1 parent cf4dda2 commit 1d6aace
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 20 deletions.
22 changes: 19 additions & 3 deletions test/invariant/Invariants.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ contract PSMInvariants_ConstantRate_NoTransfer is PSMInvariantTestBase {

targetContract(address(lpHandler));
targetContract(address(swapperHandler));

// Check that LPs used for swap assertions are correct to not get zero values
assertEq(swapperHandler.lp0(), lpHandler.lps(0));
}

function invariant_A() public view {
Expand All @@ -267,7 +270,7 @@ contract PSMInvariants_ConstantRate_NoTransfer is PSMInvariantTestBase {
_checkInvariant_C();
}

function invariant_D_test() public view {
function invariant_D() public view {
_checkInvariant_D();
}

Expand Down Expand Up @@ -321,6 +324,9 @@ contract PSMInvariants_RateSetting_NoTransfer is PSMInvariantTestBase {
targetContract(address(lpHandler));
targetContract(address(rateSetterHandler));
targetContract(address(swapperHandler));

// Check that LPs used for swap assertions are correct to not get zero values
assertEq(swapperHandler.lp0(), lpHandler.lps(0));
}

function invariant_A() public view {
Expand All @@ -331,7 +337,7 @@ contract PSMInvariants_RateSetting_NoTransfer is PSMInvariantTestBase {
_checkInvariant_B();
}

function invariant_C_rate() public view {
function invariant_C() public view {
_checkInvariant_C();
}

Expand All @@ -358,9 +364,12 @@ contract PSMInvariants_RateSetting_WithTransfers is PSMInvariantTestBase {
targetContract(address(rateSetterHandler));
targetContract(address(swapperHandler));
targetContract(address(transferHandler));

// Check that LPs used for swap assertions are correct to not get zero values
assertEq(swapperHandler.lp0(), lpHandler.lps(0));
}

function invariant_A_test() public view {
function invariant_A() public view {
_checkInvariant_A();
}

Expand Down Expand Up @@ -410,6 +419,9 @@ contract PSMInvariants_TimeBasedRateSetting_NoTransfer is PSMInvariantTestBase {
targetContract(address(lpHandler));
targetContract(address(swapperHandler));
targetContract(address(timeBasedRateHandler));

// Check that LPs used for swap assertions are correct to not get zero values
assertEq(swapperHandler.lp0(), lpHandler.lps(0));
}

function invariant_A() public view {
Expand Down Expand Up @@ -464,9 +476,13 @@ contract PSMInvariants_TimeBasedRateSetting_WithTransfers is PSMInvariantTestBas
targetContract(address(swapperHandler));
targetContract(address(timeBasedRateHandler));
targetContract(address(transferHandler));

// Check that LPs used for swap assertions are correct to not get zero values
assertEq(swapperHandler.lp0(), lpHandler.lps(0));
}

function invariant_A() public view {

_checkInvariant_A();
}

Expand Down
21 changes: 21 additions & 0 deletions test/invariant/handlers/HandlerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,25 @@ contract HandlerBase is CommonBase, StdCheatsSafe, StdUtils {
}
}

function assertApproxEqRel(
uint256 a,
uint256 b,
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
string memory err
) internal virtual {
// If the left is 0, right must be too.
if (b == 0) return assertEq(a, b, string(abi.encodePacked("assertEq - ", err)));

uint256 percentDelta = stdMath.percentDelta(a, b);

if (percentDelta > maxPercentDelta) {
console.log("Error: a ~= b not satisfied [uint]");
console.log(" Left", a);
console.log(" Right", b);
console.log(" Max % Delta [wad]", maxPercentDelta);
console.log(" % Delta [wad]", percentDelta);
revert(err);
}
}

}
2 changes: 1 addition & 1 deletion test/invariant/handlers/RateSetterHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contract RateSetterHandler is HandlerBase {
// 1. Setup and bounds

// Increase the rate by up to 20%
rate += bound(rateIncrease, 0, 0.2e27);
rate += _bound(rateIncrease, 0, 0.2e27);

// 2. Cache starting state
uint256 startingConversion = psm.convertToShares(1e18);
Expand Down
51 changes: 35 additions & 16 deletions test/invariant/handlers/SwapperHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ contract SwapperHandler is HandlerBase {

address[] public swappers;

// Used for assertions, assumption made that LpHandler is used with at least 1 LP.
address public lp0;

uint256 public swapCount;
uint256 public zeroBalanceCount;

Expand All @@ -19,15 +22,18 @@ contract SwapperHandler is HandlerBase {
MockERC20 asset0,
MockERC20 asset1,
MockERC20 asset2,
uint256 lpCount
uint256 swapperCount
) HandlerBase(psm_) {
assets[0] = asset0;
assets[1] = asset1;
assets[2] = asset2;

for (uint256 i = 0; i < lpCount; i++) {
for (uint256 i = 0; i < swapperCount; i++) {
swappers.push(makeAddr(string(abi.encodePacked("swapper-", vm.toString(i)))));
}

// Derive LP-0 address for assertion
lp0 = makeAddr("lp-0");
}

function _getAsset(uint256 indexSeed) internal view returns (MockERC20) {
Expand Down Expand Up @@ -85,11 +91,12 @@ contract SwapperHandler is HandlerBase {
);

// 2. Cache starting state
uint256 startingConversion = psm.convertToAssetValue(1e18);
uint256 startingValue = psm.getPsmTotalValue();
uint256 startingConversion = psm.convertToAssetValue(1e18);
uint256 startingConversionMillion = psm.convertToAssetValue(1e6 * 1e18);
uint256 startingConversionLp0 = psm.convertToAssetValue(psm.shares(lp0));
uint256 startingValue = psm.getPsmTotalValue();

// 3. Perform action against protocol

vm.startPrank(swapper);
assetIn.mint(swapper, amountIn);
assetIn.approve(address(psm), amountIn);
Expand All @@ -98,17 +105,29 @@ contract SwapperHandler is HandlerBase {

// 4. Perform action-specific assertions

// Performing this check with tighter bounds when there is a minimum amount in the PSM.
// Leads to more accurate assertions in the more realistic scenario.
if (psm.getPsmTotalValue() > 10_000e18) {
// Rounding because of USDC precision
assertApproxEqAbs(
psm.convertToAssetValue(1e18),
startingConversion,
1e9,
"SwapperHandler/swap/conversion-rate-change"
);
}
// Rounding because of USDC precision, a user's position can fluctuate by 2e12 per 1e18 shares
assertApproxEqAbs(
psm.convertToAssetValue(1e18),
startingConversion,
2e12,
"SwapperHandler/swap/conversion-rate-change"
);

// Demonstrate rounding scales with shares
assertApproxEqAbs(
psm.convertToAssetValue(1_000_000e18),
startingConversionMillion,
2_000_000e12, // 2e18 of value
"SwapperHandler/swap/conversion-rate-change"
);

// Position values can fluctuate by 0.00000002% on swaps
assertApproxEqRel(
psm.convertToAssetValue(psm.shares(lp0)),
startingConversionLp0,
0.000002e18,
"SwapperHandler/swap/conversion-rate-change"
);

// Rounding because of USDC precision
assertGe(
Expand Down

0 comments on commit 1d6aace

Please sign in to comment.