Skip to content

Commit

Permalink
Merge pull request #27 from dhedge/fix/TRST-M-1
Browse files Browse the repository at this point in the history
Fix for TRST-M-1
  • Loading branch information
rashtrakoff authored Sep 3, 2024
2 parents 5a0c2d1 + 0280570 commit 532b3d4
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/abstracts/L2ComptrollerV2Base.sol
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ abstract contract L2ComptrollerV2Base is OwnableUpgradeable, PausableUpgradeable

// Updating the buy token price for future checks.
if (lastTokenToBuyPrice < tokenToBuyPrice) {
lastTokenToBuyPrice = tokenToBuyPrice;
buyTokenDetails[tokenToBuy].lastTokenToBuyPrice = tokenToBuyPrice;

emit BuyTokenPriceUpdated(tokenToBuy, tokenToBuyPrice);
}
Expand Down
31 changes: 31 additions & 0 deletions test/L2Comptroller/integration-tests/BuyBack.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,37 @@ contract BuyBack is Setup {
L2ComptrollerProxy.buyBack(alice, 100e18);
}

function test_Revert_WhenBuyTokenPriceLow_AfterTokenPriceIncreasePreviously() public {
vm.startPrank(alice);

// Approve the MTA tokens to the L2Comptroller for buyback.
IERC20Upgradeable(tokenToBurnL2).safeIncreaseAllowance(address(L2ComptrollerProxy), type(uint256).max);

uint256 currentTokenPrice = tokenToBuy.tokenPrice();
uint256 newTokenPrice = currentTokenPrice + ((currentTokenPrice * uint256(5)) / uint256(10000)); // +0.05% increase

// Mocking the token price call of `tokenToBuy` such that it returns a higher price than before.
vm.mockCall(address(tokenToBuy), abi.encodeWithSignature("tokenPrice()"), abi.encode(newTokenPrice));

L2ComptrollerProxy.buyBack(alice, 100e18);

currentTokenPrice = tokenToBuy.tokenPrice();
newTokenPrice = currentTokenPrice - ((currentTokenPrice * uint256(11)) / uint256(10000)); // 0.11% deviation

// Mocking the token price call of `tokenToBuy` such that it returns a low price and beyond the limit.
vm.mockCall(address(tokenToBuy), abi.encodeWithSignature("tokenPrice()"), abi.encode(newTokenPrice));

vm.expectRevert(
abi.encodeWithSelector(
L2ComptrollerOPV1.PriceDropExceedsLimit.selector,
currentTokenPrice - ((currentTokenPrice * L2ComptrollerProxy.maxTokenPriceDrop()) / 10_000),
newTokenPrice
)
);

L2ComptrollerProxy.buyBack(alice, 100e18);
}

function test_Revert_WhenInternalBuybackFunctionCalledByAExternalCaller() public {
vm.expectRevert(abi.encodeWithSelector(L2ComptrollerOPV1.ExternalCallerNotAllowed.selector));

Expand Down
85 changes: 85 additions & 0 deletions test/L2ComptrollerV2/integration-tests/RedeemFromL1V2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ contract RedeemFromL1V2 is SetupV2 {

// Events in L2Comptroller and L1Comptroller.
event RequireErrorDuringRedemption(address indexed depositor, string reason);
event LowLevelErrorDuringRedemption(address indexed depositor, bytes reason);

function setUp() public override {
super.setUp();
Expand Down Expand Up @@ -805,4 +806,88 @@ contract RedeemFromL1V2 is SetupV2 {

vm.clearMockedCalls();
}

function test_Revert_WhenBuyTokenPriceLow_AfterTokenPriceIncreasePreviously() public {
vm.startPrank(address(L2DomainMessenger));

uint256 currentTokenPriceUSDy = USDy.tokenPrice();
uint256 currentTokenPriceUSDpy = USDpy.tokenPrice();
uint256 newTokenPriceUSDy = currentTokenPriceUSDy + ((currentTokenPriceUSDy * uint256(5)) / uint256(10000)); // +0.05% increase
uint256 newTokenPriceUSDpy = currentTokenPriceUSDpy + ((currentTokenPriceUSDpy * uint256(5)) / uint256(10000)); // +0.05% increase

// Mocking the token price call of `tokenToBuy` such that it returns a higher price than before.
vm.mockCall(address(USDy), abi.encodeWithSignature("tokenPrice()"), abi.encode(newTokenPriceUSDy));
vm.mockCall(address(USDpy), abi.encodeWithSignature("tokenPrice()"), abi.encode(newTokenPriceUSDpy));

L2ComptrollerV2Proxy.redeemFromL1({
tokenBurned: address(MTA_L1),
tokenToBuy: address(USDy),
totalAmountBurntOnL1: 100e18,
l1Depositor: alice,
receiver: alice
});

L2ComptrollerV2Proxy.redeemFromL1({
tokenBurned: address(POTATO_SWAP),
tokenToBuy: address(USDpy),
totalAmountBurntOnL1: 100e18,
l1Depositor: alice,
receiver: alice
});

currentTokenPriceUSDy = USDy.tokenPrice();
currentTokenPriceUSDpy = USDpy.tokenPrice();
newTokenPriceUSDy = currentTokenPriceUSDy - ((currentTokenPriceUSDy * uint256(100)) / uint256(10000)); // -1% decrease
newTokenPriceUSDpy = currentTokenPriceUSDpy - ((currentTokenPriceUSDpy * uint256(1100)) / uint256(10000)); // -11% decrease

(, uint256 maxTokenPriceDropUSDy) = L2ComptrollerV2Proxy.buyTokenDetails(USDy);
(, uint256 maxTokenPriceDropUSDpy) = L2ComptrollerV2Proxy.buyTokenDetails(USDpy);

// Mocking the token price call of `tokenToBuy` such that it returns a low price and beyond the limit.
vm.mockCall(address(USDy), abi.encodeWithSignature("tokenPrice()"), abi.encode(newTokenPriceUSDy));

vm.expectEmit();

emit LowLevelErrorDuringRedemption(
alice,
abi.encodeWithSelector(
L2ComptrollerV2Base.PriceDropExceedsLimit.selector,
USDy,
currentTokenPriceUSDy - ((currentTokenPriceUSDy * maxTokenPriceDropUSDy) / 10_000),
newTokenPriceUSDy
)
);

L2ComptrollerV2Proxy.redeemFromL1({
tokenBurned: address(MTA_L1),
tokenToBuy: address(USDy),
totalAmountBurntOnL1: 200e18,
l1Depositor: alice,
receiver: alice
});

vm.mockCall(address(USDpy), abi.encodeWithSignature("tokenPrice()"), abi.encode(newTokenPriceUSDpy));

vm.expectEmit();

emit LowLevelErrorDuringRedemption(
alice,
abi.encodeWithSelector(
L2ComptrollerV2Base.PriceDropExceedsLimit.selector,
USDpy,
currentTokenPriceUSDpy - ((currentTokenPriceUSDpy * maxTokenPriceDropUSDpy) / 10_000),
newTokenPriceUSDpy
)
);

L2ComptrollerV2Proxy.redeemFromL1({
tokenBurned: address(POTATO_SWAP),
tokenToBuy: address(USDpy),
totalAmountBurntOnL1: 200e18,
l1Depositor: alice,
receiver: alice
});

vm.clearMockedCalls();
}
}

0 comments on commit 532b3d4

Please sign in to comment.