/opt/scfuzzbench/work/target/lib/erc7540-reusable-properties/src/ERC7540Properties.sol
   1 |     | // SPDX-License-Identifier: AGPL-3.0-only
   2 |     | pragma solidity ^0.8.21;
   3 |     | 
   4 |     | import {Asserts} from "@chimera/Asserts.sol";
   5 |     | 
   6 |     | interface IShareLike {
   7 |     |     function balanceOf(address) external view returns (uint256);
   8 |     |     function totalSupply() external view returns (uint256);
   9 |     |     function decimals() external view returns (uint8);
  10 |     | }
  11 |     | 
  12 |     | interface IERC7540Like {
  13 |     |     function share() external view returns (address shareTokenAddress);
  14 |     |     function convertToShares(
  15 |     |         uint256 assets
  16 |     |     ) external view returns (uint256 shares);
  17 |     |     function convertToAssets(
  18 |     |         uint256 shares
  19 |     |     ) external view returns (uint256 assets);
  20 |     |     function totalAssets() external view returns (uint256 totalManagedAssets);
  21 |     |     function maxDeposit(
  22 |     |         address receiver
  23 |     |     ) external view returns (uint256 maxAssets);
  24 |     |     function previewDeposit(
  25 |     |         uint256 assets
  26 |     |     ) external view returns (uint256 shares);
  27 |     |     function deposit(
  28 |     |         uint256 assets,
  29 |     |         address receiver
  30 |     |     ) external returns (uint256 shares);
  31 |     |     function maxMint(
  32 |     |         address receiver
  33 |     |     ) external view returns (uint256 maxShares);
  34 |     |     function previewMint(uint256 shares) external view returns (uint256 assets);
  35 |     |     function mint(
  36 |     |         uint256 shares,
  37 |     |         address receiver
  38 |     |     ) external returns (uint256 assets);
  39 |     |     function maxWithdraw(
  40 |     |         address owner
  41 |     |     ) external view returns (uint256 maxAssets);
  42 |     |     function previewWithdraw(
  43 |     |         uint256 assets
  44 |     |     ) external view returns (uint256 shares);
  45 |     |     function withdraw(
  46 |     |         uint256 assets,
  47 |     |         address receiver,
  48 |     |         address owner
  49 |     |     ) external returns (uint256 shares);
  50 |     |     function maxRedeem(address owner) external view returns (uint256 maxShares);
  51 |     |     function previewRedeem(
  52 |     |         uint256 shares
  53 |     |     ) external view returns (uint256 assets);
  54 |     |     function redeem(
  55 |     |         uint256 shares,
  56 |     |         address receiver,
  57 |     |         address owner
  58 |     |     ) external returns (uint256 assets);
  59 |     | 
  60 |     |     function requestRedeem(
  61 |     |         uint256 shares,
  62 |     |         address receiver,
  63 |     |         address owner,
  64 |     |         bytes calldata data
  65 |     |     ) external returns (uint256 requestId);
  66 |     | }
  67 |     | 
  68 |     | /// @dev ERC-7540 Properties
  69 |     | /// @author The Recon Team
  70 |     | /// @notice A set of reuseable tests for your ERC7540 Vaults
  71 |     | ///     To get started, extend from this contract and make sure to add a way to set the actor (the current user)
  72 |     | ///     For more info: https://getrecon.xyz/
  73 |     | abstract contract ERC7540Properties is Asserts {
  74 | *r  |     uint256 public constant MAX_ROUNDING_ERROR = 10 ** 18;
  75 |     | 
  76 |     |     address actor;
  77 |     | 
  78 |     |     /// @audit TODO: You must add a way to change this!
  79 |     | 
  80 |     |     /// @dev 7540-1	convertToAssets(totalSupply) == totalAssets unless price is 0.0
  81 | *r  |     function erc7540_1(address erc7540Target) public virtual returns (bool) {
  82 |     |         // Doesn't hold on zero price
  83 | *   |         if (
  84 | *   |             IERC7540Like(erc7540Target).convertToAssets(
  85 | *r  |                 10 ** IShareLike(IERC7540Like(erc7540Target).share()).decimals()
  86 | *   |             ) == 0
  87 | *   |         ) return true;
  88 |     | 
  89 |     |         return
  90 | *   |             IERC7540Like(erc7540Target).convertToAssets(
  91 | *   |                 IShareLike(IERC7540Like(erc7540Target).share()).totalSupply()
  92 | *   |             ) == IERC7540Like(erc7540Target).totalAssets();
  93 |     |     }
  94 |     | 
  95 |     |     /// @dev 7540-2	convertToShares(totalAssets) == totalSupply unless price is 0.0
  96 | *r  |     function erc7540_2(address erc7540Target) public virtual returns (bool) {
  97 | *   |         if (
  98 | *   |             IERC7540Like(erc7540Target).convertToAssets(
  99 | *r  |                 10 ** IShareLike(IERC7540Like(erc7540Target).share()).decimals()
 100 | *   |             ) == 0
 101 | *   |         ) return true;
 102 |     | 
 103 |     |         // convertToShares(totalAssets) == totalSupply
 104 |     |         return
 105 | *   |             _diff(
 106 | *   |                 IERC7540Like(erc7540Target).convertToShares(
 107 | *   |                     IERC7540Like(erc7540Target).totalAssets()
 108 |     |                 ),
 109 | *   |                 IShareLike(IERC7540Like(erc7540Target).share()).totalSupply()
 110 |     |             ) <= MAX_ROUNDING_ERROR;
 111 |     |     }
 112 |     | 
 113 | *   |     function _diff(uint256 a, uint256 b) internal pure returns (uint256) {
 114 | *   |         return a > b ? a - b : b - a;
 115 |     |     }
 116 |     | 
 117 |     |     /// @dev 7540-3	max* never reverts
 118 | *r  |     function erc7540_3(address erc7540Target) public virtual returns (bool) {
 119 |     |         // max* never reverts
 120 | *   |         try IERC7540Like(erc7540Target).maxDeposit(actor) {} catch {
 121 | *   |             return false;
 122 |     |         }
 123 | *   |         try IERC7540Like(erc7540Target).maxMint(actor) {} catch {
 124 |     |             return false;
 125 |     |         }
 126 | *   |         try IERC7540Like(erc7540Target).maxRedeem(actor) {} catch {
 127 | *   |             return false;
 128 |     |         }
 129 | *   |         try IERC7540Like(erc7540Target).maxWithdraw(actor) {} catch {
 130 |     |             return false;
 131 |     |         }
 132 |     | 
 133 | *   |         return true;
 134 |     |     }
 135 |     | 
 136 |     |     /// == erc7540_4 == //
 137 |     | 
 138 |     |     /// @dev 7540-4 claiming more than max always reverts
 139 | *r  |     function erc7540_4_deposit(
 140 |     |         address erc7540Target,
 141 |     |         uint256 amt
 142 | *   |     ) public virtual returns (bool) {
 143 |     |         // Skip 0
 144 | *   |         if (amt == 0) {
 145 | *   |             return true; // Skip
 146 |     |         }
 147 |     | 
 148 | *r  |         uint256 maxDep = IERC7540Like(erc7540Target).maxDeposit(actor);
 149 |     | 
 150 |     |         /// @audit No Revert is proven by erc7540_5
 151 |     | 
 152 | *   |         uint256 sum = maxDep + amt;
 153 | *   |         if (sum == 0) {
 154 |     |             return true; // Needs to be greater than 0, skip
 155 |     |         }
 156 |     | 
 157 | *   |         try IERC7540Like(erc7540Target).deposit(maxDep + amt, actor) {
 158 |     |             return false;
 159 |     |         } catch {
 160 |     |             // We want this to be hit
 161 |     |             return true; // So we explicitly return here, as a means to ensure that this is the code path
 162 |     |         }
 163 |     | 
 164 |     |         // NOTE: This code path is never hit per the above
 165 |     |     }
 166 |     | 
 167 | *r  |     function erc7540_4_mint(
 168 |     |         address erc7540Target,
 169 |     |         uint256 amt
 170 | *   |     ) public virtual returns (bool) {
 171 |     |         // Skip 0
 172 | *   |         if (amt == 0) {
 173 | *   |             return true;
 174 |     |         }
 175 |     | 
 176 | *r  |         uint256 maxDep = IERC7540Like(erc7540Target).maxMint(actor);
 177 |     | 
 178 | *   |         uint256 sum = maxDep + amt;
 179 | *   |         if (sum == 0) {
 180 |     |             return true; // Needs to be greater than 0, skip
 181 |     |         }
 182 |     | 
 183 | *   |         try IERC7540Like(erc7540Target).mint(maxDep + amt, actor) {
 184 |     |             return false;
 185 |     |         } catch {
 186 |     |             // We want this to be hit
 187 |     |             return true; // So we explicitly return here, as a means to ensure that this is the code path
 188 |     |         }
 189 |     | 
 190 |     |         // NOTE: This code path is never hit per the above
 191 |     |     }
 192 |     | 
 193 | *r  |     function erc7540_4_withdraw(
 194 |     |         address erc7540Target,
 195 |     |         uint256 amt
 196 | *   |     ) public virtual returns (bool) {
 197 |     |         // Skip 0
 198 | *   |         if (amt == 0) {
 199 | *   |             return true;
 200 |     |         }
 201 |     | 
 202 | *r  |         uint256 maxDep = IERC7540Like(erc7540Target).maxWithdraw(actor);
 203 |     | 
 204 | *   |         uint256 sum = maxDep + amt;
 205 | *   |         if (sum == 0) {
 206 |     |             return true; // Needs to be greater than 0
 207 |     |         }
 208 |     | 
 209 | *   |         try IERC7540Like(erc7540Target).withdraw(maxDep + amt, actor, actor) {
 210 |     |             return false;
 211 |     |         } catch {
 212 |     |             // We want this to be hit
 213 |     |             return true; // So we explicitly return here, as a means to ensure that this is the code path
 214 |     |         }
 215 |     | 
 216 |     |         // NOTE: This code path is never hit per the above
 217 |     |     }
 218 |     | 
 219 | *r  |     function erc7540_4_redeem(
 220 |     |         address erc7540Target,
 221 |     |         uint256 amt
 222 | *   |     ) public virtual returns (bool) {
 223 |     |         // Skip 0
 224 | *   |         if (amt == 0) {
 225 | *   |             return true;
 226 |     |         }
 227 |     | 
 228 | *r  |         uint256 maxDep = IERC7540Like(erc7540Target).maxRedeem(actor);
 229 |     | 
 230 | *   |         uint256 sum = maxDep + amt;
 231 | *   |         if (sum == 0) {
 232 |     |             return true; // Needs to be greater than 0
 233 |     |         }
 234 |     | 
 235 | *   |         try IERC7540Like(erc7540Target).redeem(maxDep + amt, actor, actor) {
 236 |     |             return false;
 237 |     |         } catch {
 238 |     |             // We want this to be hit
 239 | *   |             return true; // So we explicitly return here, as a means to ensure that this is the code path
 240 |     |         }
 241 |     | 
 242 |     |         // NOTE: This code path is never hit per the above
 243 |     |     }
 244 |     | 
 245 |     |     /// == END erc7540_4 == //
 246 |     | 
 247 |     |     /// @dev 7540-5	requestRedeem reverts if the share balance is less than amount
 248 | *r  |     function erc7540_5(
 249 |     |         address erc7540Target,
 250 |     |         address shareToken,
 251 |     |         uint256 shares
 252 | *   |     ) public virtual returns (bool) {
 253 | *   |         if (shares == 0) {
 254 | *   |             return true; // Skip
 255 |     |         }
 256 |     | 
 257 | *r  |         uint256 actualBal = IShareLike(shareToken).balanceOf(actor);
 258 | *   |         uint256 balWeWillUse = actualBal + shares;
 259 |     | 
 260 | *   |         if (balWeWillUse == 0) {
 261 |     |             return true; // Skip
 262 |     |         }
 263 |     | 
 264 | *   |         try
 265 | *   |             IERC7540Like(erc7540Target).requestRedeem(
 266 |     |                 balWeWillUse,
 267 | *   |                 actor,
 268 |     |                 actor,
 269 |     |                 ""
 270 |     |             )
 271 |     |         {
 272 |     |             return false;
 273 |     |         } catch {
 274 | *   |             return true;
 275 |     |         }
 276 |     | 
 277 |     |         // NOTE: This code path is never hit per the above
 278 |     |     }
 279 |     | 
 280 |     |     /// @dev 7540-6	preview* always reverts
 281 | *r  |     function erc7540_6(address erc7540Target) public virtual returns (bool) {
 282 |     |         // preview* always reverts
 283 | *   |         try IERC7540Like(erc7540Target).previewDeposit(0) {
 284 | *   |             return false;
 285 |     |         } catch {}
 286 | *   |         try IERC7540Like(erc7540Target).previewMint(0) {
 287 |     |             return false;
 288 |     |         } catch {}
 289 | *   |         try IERC7540Like(erc7540Target).previewRedeem(0) {
 290 |     |             return false;
 291 |     |         } catch {}
 292 | *   |         try IERC7540Like(erc7540Target).previewWithdraw(0) {
 293 |     |             return false;
 294 |     |         } catch {}
 295 |     | 
 296 | *   |         return true;
 297 |     |     }
 298 |     | 
 299 |     |     /// == erc7540_7 == //
 300 |     | 
 301 |     |     /// @dev 7540-7 if max[method] > 0, then [method] (max) should not revert
 302 | *r  |     function erc7540_7_deposit(
 303 |     |         address erc7540Target,
 304 |     |         uint256 amt
 305 | *   |     ) public virtual returns (bool) {
 306 |     |         // Per erc7540_4
 307 | *r  |         uint256 maxDeposit = IERC7540Like(erc7540Target).maxDeposit(actor);
 308 | *   |         amt = between(amt, 0, maxDeposit);
 309 |     | 
 310 | *   |         if (amt == 0) {
 311 | *   |             return true; // Skip
 312 |     |         }
 313 |     | 
 314 | *   |         try IERC7540Like(erc7540Target).deposit(amt, actor) {
 315 |     |             // Success here
 316 |     |             return true;
 317 |     |         } catch {
 318 |     |             return false;
 319 |     |         }
 320 |     | 
 321 |     |         // NOTE: This code path is never hit per the above
 322 |     |     }
 323 |     | 
 324 | *r  |     function erc7540_7_mint(
 325 |     |         address erc7540Target,
 326 |     |         uint256 amt
 327 | *   |     ) public virtual returns (bool) {
 328 | *r  |         uint256 maxMint = IERC7540Like(erc7540Target).maxMint(actor);
 329 | *   |         amt = between(amt, 0, maxMint);
 330 |     | 
 331 | *   |         if (amt == 0) {
 332 | *   |             return true; // Skip
 333 |     |         }
 334 |     | 
 335 | *   |         try IERC7540Like(erc7540Target).mint(amt, actor) {
 336 |     |             // Success here
 337 |     |             return true;
 338 |     |         } catch {
 339 |     |             return false;
 340 |     |         }
 341 |     | 
 342 |     |         // NOTE: This code path is never hit per the above
 343 |     |     }
 344 |     | 
 345 | *r  |     function erc7540_7_withdraw(
 346 |     |         address erc7540Target,
 347 |     |         uint256 amt
 348 | *   |     ) public virtual returns (bool) {
 349 | *r  |         uint256 maxWithdraw = IERC7540Like(erc7540Target).maxWithdraw(actor);
 350 | *   |         amt = between(amt, 0, maxWithdraw);
 351 |     | 
 352 | *   |         if (amt == 0) {
 353 | *   |             return true; // Skip
 354 |     |         }
 355 |     | 
 356 | *   |         try IERC7540Like(erc7540Target).withdraw(amt, actor, actor) {
 357 |     |             // Success here
 358 | *   |             return true;
 359 |     |         } catch {
 360 | *   |             return false;
 361 |     |         }
 362 |     | 
 363 |     |         // NOTE: This code path is never hit per the above
 364 |     |     }
 365 |     | 
 366 | *r  |     function erc7540_7_redeem(
 367 |     |         address erc7540Target,
 368 |     |         uint256 amt
 369 | *   |     ) public virtual returns (bool) {
 370 |     |         // Per erc7540_4
 371 | *r  |         uint256 maxRedeem = IERC7540Like(erc7540Target).maxRedeem(actor);
 372 | *   |         amt = between(amt, 0, maxRedeem);
 373 |     | 
 374 | *   |         if (amt == 0) {
 375 | *   |             return true; // Skip
 376 |     |         }
 377 |     | 
 378 | *   |         try IERC7540Like(erc7540Target).redeem(amt, actor, actor) {
 379 |     |             return true;
 380 |     |         } catch {
 381 |     |             return false;
 382 |     |         }
 383 |     | 
 384 |     |         // NOTE: This code path is never hit per the above
 385 |     |     }
 386 |     | 
 387 |     |     /// == END erc7540_7 == //
 388 |     | }
 389 |     | 

/opt/scfuzzbench/work/target/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | /**
   7 |     |  * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
   8 |     |  * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
   9 |     |  * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
  10 |     |  * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
  11 |     |  *
  12 |     |  * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
  13 |     |  * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
  14 |     |  * case an upgrade adds a module that needs to be initialized.
  15 |     |  *
  16 |     |  * For example:
  17 |     |  *
  18 |     |  * [.hljs-theme-light.nopadding]
  19 |     |  * ```solidity
  20 |     |  * contract MyToken is ERC20Upgradeable {
  21 |     |  *     function initialize() initializer public {
  22 |     |  *         __ERC20_init("MyToken", "MTK");
  23 |     |  *     }
  24 |     |  * }
  25 |     |  *
  26 |     |  * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
  27 |     |  *     function initializeV2() reinitializer(2) public {
  28 |     |  *         __ERC20Permit_init("MyToken");
  29 |     |  *     }
  30 |     |  * }
  31 |     |  * ```
  32 |     |  *
  33 |     |  * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
  34 |     |  * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
  35 |     |  *
  36 |     |  * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
  37 |     |  * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
  38 |     |  *
  39 |     |  * [CAUTION]
  40 |     |  * ====
  41 |     |  * Avoid leaving a contract uninitialized.
  42 |     |  *
  43 |     |  * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
  44 |     |  * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
  45 |     |  * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
  46 |     |  *
  47 |     |  * [.hljs-theme-light.nopadding]
  48 |     |  * ```
  49 |     |  * /// @custom:oz-upgrades-unsafe-allow constructor
  50 |     |  * constructor() {
  51 |     |  *     _disableInitializers();
  52 |     |  * }
  53 |     |  * ```
  54 |     |  * ====
  55 |     |  */
  56 |     | abstract contract Initializable {
  57 |     |     /**
  58 |     |      * @dev Storage of the initializable contract.
  59 |     |      *
  60 |     |      * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
  61 |     |      * when using with upgradeable contracts.
  62 |     |      *
  63 |     |      * @custom:storage-location erc7201:openzeppelin.storage.Initializable
  64 |     |      */
  65 |     |     struct InitializableStorage {
  66 |     |         /**
  67 |     |          * @dev Indicates that the contract has been initialized.
  68 |     |          */
  69 |     |         uint64 _initialized;
  70 |     |         /**
  71 |     |          * @dev Indicates that the contract is in the process of being initialized.
  72 |     |          */
  73 |     |         bool _initializing;
  74 |     |     }
  75 |     | 
  76 |     |     // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
  77 | *   |     bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
  78 |     | 
  79 |     |     /**
  80 |     |      * @dev The contract is already initialized.
  81 |     |      */
  82 |     |     error InvalidInitialization();
  83 |     | 
  84 |     |     /**
  85 |     |      * @dev The contract is not initializing.
  86 |     |      */
  87 |     |     error NotInitializing();
  88 |     | 
  89 |     |     /**
  90 |     |      * @dev Triggered when the contract has been initialized or reinitialized.
  91 |     |      */
  92 |     |     event Initialized(uint64 version);
  93 |     | 
  94 |     |     /**
  95 |     |      * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
  96 |     |      * `onlyInitializing` functions can be used to initialize parent contracts.
  97 |     |      *
  98 |     |      * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
  99 |     |      * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
 100 |     |      * production.
 101 |     |      *
 102 |     |      * Emits an {Initialized} event.
 103 |     |      */
 104 | *   |     modifier initializer() {
 105 |     |         // solhint-disable-next-line var-name-mixedcase
 106 | *   |         InitializableStorage storage $ = _getInitializableStorage();
 107 |     | 
 108 |     |         // Cache values to avoid duplicated sloads
 109 | *   |         bool isTopLevelCall = !$._initializing;
 110 | *   |         uint64 initialized = $._initialized;
 111 |     | 
 112 |     |         // Allowed calls:
 113 |     |         // - initialSetup: the contract is not in the initializing state and no previous version was
 114 |     |         //                 initialized
 115 |     |         // - construction: the contract is initialized at version 1 (no reinitialization) and the
 116 |     |         //                 current contract is just being deployed
 117 | *   |         bool initialSetup = initialized == 0 && isTopLevelCall;
 118 | *   |         bool construction = initialized == 1 && address(this).code.length == 0;
 119 |     | 
 120 | *   |         if (!initialSetup && !construction) {
 121 |     |             revert InvalidInitialization();
 122 |     |         }
 123 | *   |         $._initialized = 1;
 124 | *   |         if (isTopLevelCall) {
 125 | *   |             $._initializing = true;
 126 |     |         }
 127 |     |         _;
 128 | *   |         if (isTopLevelCall) {
 129 | *   |             $._initializing = false;
 130 | *   |             emit Initialized(1);
 131 |     |         }
 132 |     |     }
 133 |     | 
 134 |     |     /**
 135 |     |      * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
 136 |     |      * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
 137 |     |      * used to initialize parent contracts.
 138 |     |      *
 139 |     |      * A reinitializer may be used after the original initialization step. This is essential to configure modules that
 140 |     |      * are added through upgrades and that require initialization.
 141 |     |      *
 142 |     |      * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
 143 |     |      * cannot be nested. If one is invoked in the context of another, execution will revert.
 144 |     |      *
 145 |     |      * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
 146 |     |      * a contract, executing them in the right order is up to the developer or operator.
 147 |     |      *
 148 |     |      * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
 149 |     |      *
 150 |     |      * Emits an {Initialized} event.
 151 |     |      */
 152 |     |     modifier reinitializer(uint64 version) {
 153 |     |         // solhint-disable-next-line var-name-mixedcase
 154 |     |         InitializableStorage storage $ = _getInitializableStorage();
 155 |     | 
 156 |     |         if ($._initializing || $._initialized >= version) {
 157 |     |             revert InvalidInitialization();
 158 |     |         }
 159 |     |         $._initialized = version;
 160 |     |         $._initializing = true;
 161 |     |         _;
 162 |     |         $._initializing = false;
 163 |     |         emit Initialized(version);
 164 |     |     }
 165 |     | 
 166 |     |     /**
 167 |     |      * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
 168 |     |      * {initializer} and {reinitializer} modifiers, directly or indirectly.
 169 |     |      */
 170 |     |     modifier onlyInitializing() {
 171 | *   |         _checkInitializing();
 172 |     |         _;
 173 |     |     }
 174 |     | 
 175 |     |     /**
 176 |     |      * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
 177 |     |      */
 178 | *   |     function _checkInitializing() internal view virtual {
 179 | *   |         if (!_isInitializing()) {
 180 |     |             revert NotInitializing();
 181 |     |         }
 182 |     |     }
 183 |     | 
 184 |     |     /**
 185 |     |      * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
 186 |     |      * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
 187 |     |      * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
 188 |     |      * through proxies.
 189 |     |      *
 190 |     |      * Emits an {Initialized} event the first time it is successfully executed.
 191 |     |      */
 192 | *   |     function _disableInitializers() internal virtual {
 193 |     |         // solhint-disable-next-line var-name-mixedcase
 194 |     |         InitializableStorage storage $ = _getInitializableStorage();
 195 |     | 
 196 | *   |         if ($._initializing) {
 197 |     |             revert InvalidInitialization();
 198 |     |         }
 199 | *   |         if ($._initialized != type(uint64).max) {
 200 | *   |             $._initialized = type(uint64).max;
 201 | *   |             emit Initialized(type(uint64).max);
 202 |     |         }
 203 |     |     }
 204 |     | 
 205 |     |     /**
 206 |     |      * @dev Returns the highest version that has been initialized. See {reinitializer}.
 207 |     |      */
 208 |     |     function _getInitializedVersion() internal view returns (uint64) {
 209 |     |         return _getInitializableStorage()._initialized;
 210 |     |     }
 211 |     | 
 212 |     |     /**
 213 |     |      * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
 214 |     |      */
 215 | *   |     function _isInitializing() internal view returns (bool) {
 216 | *   |         return _getInitializableStorage()._initializing;
 217 |     |     }
 218 |     | 
 219 |     |     /**
 220 |     |      * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
 221 |     |      *
 222 |     |      * NOTE: Consider following the ERC-7201 formula to derive storage locations.
 223 |     |      */
 224 | *   |     function _initializableStorageSlot() internal pure virtual returns (bytes32) {
 225 |     |         return INITIALIZABLE_STORAGE;
 226 |     |     }
 227 |     | 
 228 |     |     /**
 229 |     |      * @dev Returns a pointer to the storage namespace.
 230 |     |      */
 231 |     |     // solhint-disable-next-line var-name-mixedcase
 232 | *   |     function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
 233 | *   |         bytes32 slot = _initializableStorageSlot();
 234 |     |         assembly {
 235 |     |             $.slot := slot
 236 |     |         }
 237 |     |     }
 238 |     | }
 239 |     | 

/opt/scfuzzbench/work/target/lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   7 |     | import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
   8 |     | import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol";
   9 |     | import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
  10 |     | import {Initializable} from "../../proxy/utils/Initializable.sol";
  11 |     | 
  12 |     | /**
  13 |     |  * @dev Implementation of the {IERC20} interface.
  14 |     |  *
  15 |     |  * This implementation is agnostic to the way tokens are created. This means
  16 |     |  * that a supply mechanism has to be added in a derived contract using {_mint}.
  17 |     |  *
  18 |     |  * TIP: For a detailed writeup see our guide
  19 |     |  * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
  20 |     |  * to implement supply mechanisms].
  21 |     |  *
  22 |     |  * The default value of {decimals} is 18. To change this, you should override
  23 |     |  * this function so it returns a different value.
  24 |     |  *
  25 |     |  * We have followed general OpenZeppelin Contracts guidelines: functions revert
  26 |     |  * instead returning `false` on failure. This behavior is nonetheless
  27 |     |  * conventional and does not conflict with the expectations of ERC-20
  28 |     |  * applications.
  29 |     |  */
  30 |     | abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {
  31 |     |     /// @custom:storage-location erc7201:openzeppelin.storage.ERC20
  32 |     |     struct ERC20Storage {
  33 |     |         mapping(address account => uint256) _balances;
  34 |     | 
  35 |     |         mapping(address account => mapping(address spender => uint256)) _allowances;
  36 |     | 
  37 |     |         uint256 _totalSupply;
  38 |     | 
  39 |     |         string _name;
  40 |     |         string _symbol;
  41 |     |     }
  42 |     | 
  43 |     |     // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff))
  44 |     |     bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;
  45 |     | 
  46 |     |     function _getERC20Storage() private pure returns (ERC20Storage storage $) {
  47 |     |         assembly {
  48 |     |             $.slot := ERC20StorageLocation
  49 |     |         }
  50 |     |     }
  51 |     | 
  52 |     |     /**
  53 |     |      * @dev Sets the values for {name} and {symbol}.
  54 |     |      *
  55 |     |      * Both values are immutable: they can only be set once during construction.
  56 |     |      */
  57 | *   |     function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
  58 | *   |         __ERC20_init_unchained(name_, symbol_);
  59 |     |     }
  60 |     | 
  61 | *   |     function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
  62 |     |         ERC20Storage storage $ = _getERC20Storage();
  63 | *   |         $._name = name_;
  64 | *   |         $._symbol = symbol_;
  65 |     |     }
  66 |     | 
  67 |     |     /**
  68 |     |      * @dev Returns the name of the token.
  69 |     |      */
  70 |     |     function name() public view virtual returns (string memory) {
  71 |     |         ERC20Storage storage $ = _getERC20Storage();
  72 |     |         return $._name;
  73 |     |     }
  74 |     | 
  75 |     |     /**
  76 |     |      * @dev Returns the symbol of the token, usually a shorter version of the
  77 |     |      * name.
  78 |     |      */
  79 |     |     function symbol() public view virtual returns (string memory) {
  80 |     |         ERC20Storage storage $ = _getERC20Storage();
  81 |     |         return $._symbol;
  82 |     |     }
  83 |     | 
  84 |     |     /**
  85 |     |      * @dev Returns the number of decimals used to get its user representation.
  86 |     |      * For example, if `decimals` equals `2`, a balance of `505` tokens should
  87 |     |      * be displayed to a user as `5.05` (`505 / 10 ** 2`).
  88 |     |      *
  89 |     |      * Tokens usually opt for a value of 18, imitating the relationship between
  90 |     |      * Ether and Wei. This is the default value returned by this function, unless
  91 |     |      * it's overridden.
  92 |     |      *
  93 |     |      * NOTE: This information is only used for _display_ purposes: it in
  94 |     |      * no way affects any of the arithmetic of the contract, including
  95 |     |      * {IERC20-balanceOf} and {IERC20-transfer}.
  96 |     |      */
  97 |     |     function decimals() public view virtual returns (uint8) {
  98 |     |         return 18;
  99 |     |     }
 100 |     | 
 101 |     |     /// @inheritdoc IERC20
 102 | *   |     function totalSupply() public view virtual returns (uint256) {
 103 |     |         ERC20Storage storage $ = _getERC20Storage();
 104 | *   |         return $._totalSupply;
 105 |     |     }
 106 |     | 
 107 |     |     /// @inheritdoc IERC20
 108 | *   |     function balanceOf(address account) public view virtual returns (uint256) {
 109 |     |         ERC20Storage storage $ = _getERC20Storage();
 110 | *   |         return $._balances[account];
 111 |     |     }
 112 |     | 
 113 |     |     /**
 114 |     |      * @dev See {IERC20-transfer}.
 115 |     |      *
 116 |     |      * Requirements:
 117 |     |      *
 118 |     |      * - `to` cannot be the zero address.
 119 |     |      * - the caller must have a balance of at least `value`.
 120 |     |      */
 121 | *   |     function transfer(address to, uint256 value) public virtual returns (bool) {
 122 |     |         address owner = _msgSender();
 123 | *   |         _transfer(owner, to, value);
 124 |     |         return true;
 125 |     |     }
 126 |     | 
 127 |     |     /// @inheritdoc IERC20
 128 | *   |     function allowance(address owner, address spender) public view virtual returns (uint256) {
 129 |     |         ERC20Storage storage $ = _getERC20Storage();
 130 | *   |         return $._allowances[owner][spender];
 131 |     |     }
 132 |     | 
 133 |     |     /**
 134 |     |      * @dev See {IERC20-approve}.
 135 |     |      *
 136 |     |      * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
 137 |     |      * `transferFrom`. This is semantically equivalent to an infinite approval.
 138 |     |      *
 139 |     |      * Requirements:
 140 |     |      *
 141 |     |      * - `spender` cannot be the zero address.
 142 |     |      */
 143 | *   |     function approve(address spender, uint256 value) public virtual returns (bool) {
 144 |     |         address owner = _msgSender();
 145 | *   |         _approve(owner, spender, value);
 146 | *   |         return true;
 147 |     |     }
 148 |     | 
 149 |     |     /**
 150 |     |      * @dev See {IERC20-transferFrom}.
 151 |     |      *
 152 |     |      * Skips emitting an {Approval} event indicating an allowance update. This is not
 153 |     |      * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
 154 |     |      *
 155 |     |      * NOTE: Does not update the allowance if the current allowance
 156 |     |      * is the maximum `uint256`.
 157 |     |      *
 158 |     |      * Requirements:
 159 |     |      *
 160 |     |      * - `from` and `to` cannot be the zero address.
 161 |     |      * - `from` must have a balance of at least `value`.
 162 |     |      * - the caller must have allowance for ``from``'s tokens of at least
 163 |     |      * `value`.
 164 |     |      */
 165 | *   |     function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
 166 |     |         address spender = _msgSender();
 167 | *   |         _spendAllowance(from, spender, value);
 168 | *   |         _transfer(from, to, value);
 169 | *   |         return true;
 170 |     |     }
 171 |     | 
 172 |     |     /**
 173 |     |      * @dev Moves a `value` amount of tokens from `from` to `to`.
 174 |     |      *
 175 |     |      * This internal function is equivalent to {transfer}, and can be used to
 176 |     |      * e.g. implement automatic token fees, slashing mechanisms, etc.
 177 |     |      *
 178 |     |      * Emits a {Transfer} event.
 179 |     |      *
 180 |     |      * NOTE: This function is not virtual, {_update} should be overridden instead.
 181 |     |      */
 182 | *   |     function _transfer(address from, address to, uint256 value) internal {
 183 | *   |         if (from == address(0)) {
 184 |     |             revert ERC20InvalidSender(address(0));
 185 |     |         }
 186 | *   |         if (to == address(0)) {
 187 |     |             revert ERC20InvalidReceiver(address(0));
 188 |     |         }
 189 | *   |         _update(from, to, value);
 190 |     |     }
 191 |     | 
 192 |     |     /**
 193 |     |      * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
 194 |     |      * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
 195 |     |      * this function.
 196 |     |      *
 197 |     |      * Emits a {Transfer} event.
 198 |     |      */
 199 | *   |     function _update(address from, address to, uint256 value) internal virtual {
 200 |     |         ERC20Storage storage $ = _getERC20Storage();
 201 | *   |         if (from == address(0)) {
 202 |     |             // Overflow check required: The rest of the code assumes that totalSupply never overflows
 203 | *   |             $._totalSupply += value;
 204 |     |         } else {
 205 | *   |             uint256 fromBalance = $._balances[from];
 206 | *   |             if (fromBalance < value) {
 207 | *   |                 revert ERC20InsufficientBalance(from, fromBalance, value);
 208 |     |             }
 209 |     |             unchecked {
 210 |     |                 // Overflow not possible: value <= fromBalance <= totalSupply.
 211 | *   |                 $._balances[from] = fromBalance - value;
 212 |     |             }
 213 |     |         }
 214 |     | 
 215 | *   |         if (to == address(0)) {
 216 |     |             unchecked {
 217 |     |                 // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
 218 | *   |                 $._totalSupply -= value;
 219 |     |             }
 220 |     |         } else {
 221 |     |             unchecked {
 222 |     |                 // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
 223 | *   |                 $._balances[to] += value;
 224 |     |             }
 225 |     |         }
 226 |     | 
 227 | *   |         emit Transfer(from, to, value);
 228 |     |     }
 229 |     | 
 230 |     |     /**
 231 |     |      * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
 232 |     |      * Relies on the `_update` mechanism
 233 |     |      *
 234 |     |      * Emits a {Transfer} event with `from` set to the zero address.
 235 |     |      *
 236 |     |      * NOTE: This function is not virtual, {_update} should be overridden instead.
 237 |     |      */
 238 | *   |     function _mint(address account, uint256 value) internal {
 239 | *   |         if (account == address(0)) {
 240 |     |             revert ERC20InvalidReceiver(address(0));
 241 |     |         }
 242 | *   |         _update(address(0), account, value);
 243 |     |     }
 244 |     | 
 245 |     |     /**
 246 |     |      * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
 247 |     |      * Relies on the `_update` mechanism.
 248 |     |      *
 249 |     |      * Emits a {Transfer} event with `to` set to the zero address.
 250 |     |      *
 251 |     |      * NOTE: This function is not virtual, {_update} should be overridden instead
 252 |     |      */
 253 | *   |     function _burn(address account, uint256 value) internal {
 254 | *   |         if (account == address(0)) {
 255 |     |             revert ERC20InvalidSender(address(0));
 256 |     |         }
 257 | *   |         _update(account, address(0), value);
 258 |     |     }
 259 |     | 
 260 |     |     /**
 261 |     |      * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
 262 |     |      *
 263 |     |      * This internal function is equivalent to `approve`, and can be used to
 264 |     |      * e.g. set automatic allowances for certain subsystems, etc.
 265 |     |      *
 266 |     |      * Emits an {Approval} event.
 267 |     |      *
 268 |     |      * Requirements:
 269 |     |      *
 270 |     |      * - `owner` cannot be the zero address.
 271 |     |      * - `spender` cannot be the zero address.
 272 |     |      *
 273 |     |      * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
 274 |     |      */
 275 | *   |     function _approve(address owner, address spender, uint256 value) internal {
 276 | *   |         _approve(owner, spender, value, true);
 277 |     |     }
 278 |     | 
 279 |     |     /**
 280 |     |      * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
 281 |     |      *
 282 |     |      * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
 283 |     |      * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
 284 |     |      * `Approval` event during `transferFrom` operations.
 285 |     |      *
 286 |     |      * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
 287 |     |      * true using the following override:
 288 |     |      *
 289 |     |      * ```solidity
 290 |     |      * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
 291 |     |      *     super._approve(owner, spender, value, true);
 292 |     |      * }
 293 |     |      * ```
 294 |     |      *
 295 |     |      * Requirements are the same as {_approve}.
 296 |     |      */
 297 | *   |     function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
 298 |     |         ERC20Storage storage $ = _getERC20Storage();
 299 | *   |         if (owner == address(0)) {
 300 |     |             revert ERC20InvalidApprover(address(0));
 301 |     |         }
 302 | *   |         if (spender == address(0)) {
 303 | *   |             revert ERC20InvalidSpender(address(0));
 304 |     |         }
 305 | *   |         $._allowances[owner][spender] = value;
 306 | *   |         if (emitEvent) {
 307 | *   |             emit Approval(owner, spender, value);
 308 |     |         }
 309 |     |     }
 310 |     | 
 311 |     |     /**
 312 |     |      * @dev Updates `owner`'s allowance for `spender` based on spent `value`.
 313 |     |      *
 314 |     |      * Does not update the allowance value in case of infinite allowance.
 315 |     |      * Revert if not enough allowance is available.
 316 |     |      *
 317 |     |      * Does not emit an {Approval} event.
 318 |     |      */
 319 | *   |     function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
 320 | *   |         uint256 currentAllowance = allowance(owner, spender);
 321 | *   |         if (currentAllowance < type(uint256).max) {
 322 | *   |             if (currentAllowance < value) {
 323 | *   |                 revert ERC20InsufficientAllowance(spender, currentAllowance, value);
 324 |     |             }
 325 |     |             unchecked {
 326 | *   |                 _approve(owner, spender, currentAllowance - value, false);
 327 |     |             }
 328 |     |         }
 329 |     |     }
 330 |     | }
 331 |     | 

/opt/scfuzzbench/work/target/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | import {Initializable} from "../proxy/utils/Initializable.sol";
  6 |     | 
  7 |     | /**
  8 |     |  * @dev Provides information about the current execution context, including the
  9 |     |  * sender of the transaction and its data. While these are generally available
 10 |     |  * via msg.sender and msg.data, they should not be accessed in such a direct
 11 |     |  * manner, since when dealing with meta-transactions the account sending and
 12 |     |  * paying for execution may not be the actual sender (as far as an application
 13 |     |  * is concerned).
 14 |     |  *
 15 |     |  * This contract is only required for intermediate, library-like contracts.
 16 |     |  */
 17 |     | abstract contract ContextUpgradeable is Initializable {
 18 |     |     function __Context_init() internal onlyInitializing {
 19 |     |     }
 20 |     | 
 21 |     |     function __Context_init_unchained() internal onlyInitializing {
 22 |     |     }
 23 |     |     function _msgSender() internal view virtual returns (address) {
 24 | *   |         return msg.sender;
 25 |     |     }
 26 |     | 
 27 |     |     function _msgData() internal view virtual returns (bytes calldata) {
 28 |     |         return msg.data;
 29 |     |     }
 30 |     | 
 31 |     |     function _contextSuffixLength() internal view virtual returns (uint256) {
 32 |     |         return 0;
 33 |     |     }
 34 |     | }
 35 |     | 

/opt/scfuzzbench/work/target/lib/openzeppelin-contracts-upgradeable/contracts/utils/ReentrancyGuardUpgradeable.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | import {Initializable} from "../proxy/utils/Initializable.sol";
   6 |     | 
   7 |     | /**
   8 |     |  * @dev Contract module that helps prevent reentrant calls to a function.
   9 |     |  *
  10 |     |  * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
  11 |     |  * available, which can be applied to functions to make sure there are no nested
  12 |     |  * (reentrant) calls to them.
  13 |     |  *
  14 |     |  * Note that because there is a single `nonReentrant` guard, functions marked as
  15 |     |  * `nonReentrant` may not call one another. This can be worked around by making
  16 |     |  * those functions `private`, and then adding `external` `nonReentrant` entry
  17 |     |  * points to them.
  18 |     |  *
  19 |     |  * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
  20 |     |  * consider using {ReentrancyGuardTransient} instead.
  21 |     |  *
  22 |     |  * TIP: If you would like to learn more about reentrancy and alternative ways
  23 |     |  * to protect against it, check out our blog post
  24 |     |  * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
  25 |     |  */
  26 |     | abstract contract ReentrancyGuardUpgradeable is Initializable {
  27 |     |     // Booleans are more expensive than uint256 or any type that takes up a full
  28 |     |     // word because each write operation emits an extra SLOAD to first read the
  29 |     |     // slot's contents, replace the bits taken up by the boolean, and then write
  30 |     |     // back. This is the compiler's defense against contract upgrades and
  31 |     |     // pointer aliasing, and it cannot be disabled.
  32 |     | 
  33 |     |     // The values being non-zero value makes deployment a bit more expensive,
  34 |     |     // but in exchange the refund on every call to nonReentrant will be lower in
  35 |     |     // amount. Since refunds are capped to a percentage of the total
  36 |     |     // transaction's gas, it is best to keep them low in cases like this one, to
  37 |     |     // increase the likelihood of the full refund coming into effect.
  38 | *   |     uint256 private constant NOT_ENTERED = 1;
  39 | *   |     uint256 private constant ENTERED = 2;
  40 |     | 
  41 |     |     /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard
  42 |     |     struct ReentrancyGuardStorage {
  43 |     |         uint256 _status;
  44 |     |     }
  45 |     | 
  46 |     |     // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
  47 |     |     bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;
  48 |     | 
  49 |     |     function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {
  50 |     |         assembly {
  51 |     |             $.slot := ReentrancyGuardStorageLocation
  52 |     |         }
  53 |     |     }
  54 |     | 
  55 |     |     /**
  56 |     |      * @dev Unauthorized reentrant call.
  57 |     |      */
  58 |     |     error ReentrancyGuardReentrantCall();
  59 |     | 
  60 | *   |     function __ReentrancyGuard_init() internal onlyInitializing {
  61 | *   |         __ReentrancyGuard_init_unchained();
  62 |     |     }
  63 |     | 
  64 | *   |     function __ReentrancyGuard_init_unchained() internal onlyInitializing {
  65 |     |         ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
  66 |     |         $._status = NOT_ENTERED;
  67 |     |     }
  68 |     | 
  69 |     |     /**
  70 |     |      * @dev Prevents a contract from calling itself, directly or indirectly.
  71 |     |      * Calling a `nonReentrant` function from another `nonReentrant`
  72 |     |      * function is not supported. It is possible to prevent this from happening
  73 |     |      * by making the `nonReentrant` function external, and making it call a
  74 |     |      * `private` function that does the actual work.
  75 |     |      */
  76 |     |     modifier nonReentrant() {
  77 | *   |         _nonReentrantBefore();
  78 |     |         _;
  79 | *   |         _nonReentrantAfter();
  80 |     |     }
  81 |     | 
  82 | *   |     function _nonReentrantBefore() private {
  83 |     |         ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
  84 |     |         // On the first call to nonReentrant, _status will be NOT_ENTERED
  85 | *   |         if ($._status == ENTERED) {
  86 |     |             revert ReentrancyGuardReentrantCall();
  87 |     |         }
  88 |     | 
  89 |     |         // Any calls to nonReentrant after this point will fail
  90 | *   |         $._status = ENTERED;
  91 |     |     }
  92 |     | 
  93 | *   |     function _nonReentrantAfter() private {
  94 |     |         ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
  95 |     |         // By storing the original value once again, a refund is triggered (see
  96 |     |         // https://eips.ethereum.org/EIPS/eip-2200)
  97 | *   |         $._status = NOT_ENTERED;
  98 |     |     }
  99 |     | 
 100 |     |     /**
 101 |     |      * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
 102 |     |      * `nonReentrant` function in the call stack.
 103 |     |      */
 104 |     |     function _reentrancyGuardEntered() internal view returns (bool) {
 105 |     |         ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
 106 |     |         return $._status == ENTERED;
 107 |     |     }
 108 |     | }
 109 |     | 

/opt/scfuzzbench/work/target/lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.4.0) (utils/cryptography/EIP712.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
   7 |     | import {IERC5267} from "@openzeppelin/contracts/interfaces/IERC5267.sol";
   8 |     | import {Initializable} from "../../proxy/utils/Initializable.sol";
   9 |     | 
  10 |     | /**
  11 |     |  * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.
  12 |     |  *
  13 |     |  * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
  14 |     |  * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract
  15 |     |  * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to
  16 |     |  * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.
  17 |     |  *
  18 |     |  * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
  19 |     |  * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
  20 |     |  * ({_hashTypedDataV4}).
  21 |     |  *
  22 |     |  * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
  23 |     |  * the chain id to protect against replay attacks on an eventual fork of the chain.
  24 |     |  *
  25 |     |  * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
  26 |     |  * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
  27 |     |  *
  28 |     |  * NOTE: The upgradeable version of this contract does not use an immutable cache and recomputes the domain separator
  29 |     |  * each time {_domainSeparatorV4} is called. That is cheaper than accessing a cached version in cold storage.
  30 |     |  */
  31 |     | abstract contract EIP712Upgradeable is Initializable, IERC5267 {
  32 |     |     bytes32 private constant TYPE_HASH =
  33 |     |         keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
  34 |     | 
  35 |     |     /// @custom:storage-location erc7201:openzeppelin.storage.EIP712
  36 |     |     struct EIP712Storage {
  37 |     |         /// @custom:oz-renamed-from _HASHED_NAME
  38 |     |         bytes32 _hashedName;
  39 |     |         /// @custom:oz-renamed-from _HASHED_VERSION
  40 |     |         bytes32 _hashedVersion;
  41 |     | 
  42 |     |         string _name;
  43 |     |         string _version;
  44 |     |     }
  45 |     | 
  46 |     |     // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.EIP712")) - 1)) & ~bytes32(uint256(0xff))
  47 |     |     bytes32 private constant EIP712StorageLocation = 0xa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100;
  48 |     | 
  49 |     |     function _getEIP712Storage() private pure returns (EIP712Storage storage $) {
  50 |     |         assembly {
  51 |     |             $.slot := EIP712StorageLocation
  52 |     |         }
  53 |     |     }
  54 |     | 
  55 |     |     /**
  56 |     |      * @dev Initializes the domain separator and parameter caches.
  57 |     |      *
  58 |     |      * The meaning of `name` and `version` is specified in
  59 |     |      * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:
  60 |     |      *
  61 |     |      * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
  62 |     |      * - `version`: the current major version of the signing domain.
  63 |     |      *
  64 |     |      * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
  65 |     |      * contract upgrade].
  66 |     |      */
  67 | *   |     function __EIP712_init(string memory name, string memory version) internal onlyInitializing {
  68 | *   |         __EIP712_init_unchained(name, version);
  69 |     |     }
  70 |     | 
  71 | *   |     function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {
  72 |     |         EIP712Storage storage $ = _getEIP712Storage();
  73 | *   |         $._name = name;
  74 | *   |         $._version = version;
  75 |     | 
  76 |     |         // Reset prior values in storage if upgrading
  77 | *   |         $._hashedName = 0;
  78 | *   |         $._hashedVersion = 0;
  79 |     |     }
  80 |     | 
  81 |     |     /**
  82 |     |      * @dev Returns the domain separator for the current chain.
  83 |     |      */
  84 |     |     function _domainSeparatorV4() internal view returns (bytes32) {
  85 |     |         return _buildDomainSeparator();
  86 |     |     }
  87 |     | 
  88 |     |     function _buildDomainSeparator() private view returns (bytes32) {
  89 |     |         return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this)));
  90 |     |     }
  91 |     | 
  92 |     |     /**
  93 |     |      * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
  94 |     |      * function returns the hash of the fully encoded EIP712 message for this domain.
  95 |     |      *
  96 |     |      * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
  97 |     |      *
  98 |     |      * ```solidity
  99 |     |      * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
 100 |     |      *     keccak256("Mail(address to,string contents)"),
 101 |     |      *     mailTo,
 102 |     |      *     keccak256(bytes(mailContents))
 103 |     |      * )));
 104 |     |      * address signer = ECDSA.recover(digest, signature);
 105 |     |      * ```
 106 |     |      */
 107 |     |     function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
 108 |     |         return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
 109 |     |     }
 110 |     | 
 111 |     |     /// @inheritdoc IERC5267
 112 |     |     function eip712Domain()
 113 |     |         public
 114 |     |         view
 115 |     |         virtual
 116 |     |         returns (
 117 |     |             bytes1 fields,
 118 |     |             string memory name,
 119 |     |             string memory version,
 120 |     |             uint256 chainId,
 121 |     |             address verifyingContract,
 122 |     |             bytes32 salt,
 123 |     |             uint256[] memory extensions
 124 |     |         )
 125 |     |     {
 126 |     |         EIP712Storage storage $ = _getEIP712Storage();
 127 |     |         // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized
 128 |     |         // and the EIP712 domain is not reliable, as it will be missing name and version.
 129 | *   |         require($._hashedName == 0 && $._hashedVersion == 0, "EIP712: Uninitialized");
 130 |     | 
 131 |     |         return (
 132 |     |             hex"0f", // 01111
 133 |     |             _EIP712Name(),
 134 |     |             _EIP712Version(),
 135 |     |             block.chainid,
 136 |     |             address(this),
 137 |     |             bytes32(0),
 138 |     |             new uint256[](0)
 139 |     |         );
 140 |     |     }
 141 |     | 
 142 |     |     /**
 143 |     |      * @dev The name parameter for the EIP712 domain.
 144 |     |      *
 145 |     |      * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
 146 |     |      * are a concern.
 147 |     |      */
 148 |     |     function _EIP712Name() internal view virtual returns (string memory) {
 149 |     |         EIP712Storage storage $ = _getEIP712Storage();
 150 |     |         return $._name;
 151 |     |     }
 152 |     | 
 153 |     |     /**
 154 |     |      * @dev The version parameter for the EIP712 domain.
 155 |     |      *
 156 |     |      * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
 157 |     |      * are a concern.
 158 |     |      */
 159 |     |     function _EIP712Version() internal view virtual returns (string memory) {
 160 |     |         EIP712Storage storage $ = _getEIP712Storage();
 161 |     |         return $._version;
 162 |     |     }
 163 |     | 
 164 |     |     /**
 165 |     |      * @dev The hash of the name parameter for the EIP712 domain.
 166 |     |      *
 167 |     |      * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead.
 168 |     |      */
 169 |     |     function _EIP712NameHash() internal view returns (bytes32) {
 170 |     |         EIP712Storage storage $ = _getEIP712Storage();
 171 |     |         string memory name = _EIP712Name();
 172 |     |         if (bytes(name).length > 0) {
 173 |     |             return keccak256(bytes(name));
 174 |     |         } else {
 175 |     |             // If the name is empty, the contract may have been upgraded without initializing the new storage.
 176 |     |             // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design.
 177 |     |             bytes32 hashedName = $._hashedName;
 178 |     |             if (hashedName != 0) {
 179 |     |                 return hashedName;
 180 |     |             } else {
 181 |     |                 return keccak256("");
 182 |     |             }
 183 |     |         }
 184 |     |     }
 185 |     | 
 186 |     |     /**
 187 |     |      * @dev The hash of the version parameter for the EIP712 domain.
 188 |     |      *
 189 |     |      * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead.
 190 |     |      */
 191 |     |     function _EIP712VersionHash() internal view returns (bytes32) {
 192 |     |         EIP712Storage storage $ = _getEIP712Storage();
 193 |     |         string memory version = _EIP712Version();
 194 |     |         if (bytes(version).length > 0) {
 195 |     |             return keccak256(bytes(version));
 196 |     |         } else {
 197 |     |             // If the version is empty, the contract may have been upgraded without initializing the new storage.
 198 |     |             // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design.
 199 |     |             bytes32 hashedVersion = $._hashedVersion;
 200 |     |             if (hashedVersion != 0) {
 201 |     |                 return hashedVersion;
 202 |     |             } else {
 203 |     |                 return keccak256("");
 204 |     |             }
 205 |     |         }
 206 |     |     }
 207 |     | }
 208 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/lib/chimera/src/Asserts.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | abstract contract Asserts {
  5 |     |     function gt(uint256 a, uint256 b, string memory reason) internal virtual;
  6 |     | 
  7 |     |     function gte(uint256 a, uint256 b, string memory reason) internal virtual;
  8 |     | 
  9 |     |     function lt(uint256 a, uint256 b, string memory reason) internal virtual;
 10 |     | 
 11 |     |     function lte(uint256 a, uint256 b, string memory reason) internal virtual;
 12 |     | 
 13 |     |     function eq(uint256 a, uint256 b, string memory reason) internal virtual;
 14 |     | 
 15 |     |     function t(bool b, string memory reason) internal virtual;
 16 |     | 
 17 |     |     function between(uint256 value, uint256 low, uint256 high) internal virtual returns (uint256);
 18 |     | 
 19 |     |     function between(int256 value, int256 low, int256 high) internal virtual returns (int256);
 20 |     | 
 21 |     |     function precondition(bool p) internal virtual;
 22 |     | }
 23 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/lib/chimera/src/BaseProperties.sol
 1 |     | // SPDX-License-Identifier: MIT
 2 |     | pragma solidity ^0.8.0;
 3 |     | 
 4 |     | import {BaseSetup} from "./BaseSetup.sol";
 5 |     | 
 6 |     | abstract contract BaseProperties is BaseSetup {}
 7 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/lib/chimera/src/BaseSetup.sol
 1 |     | // SPDX-License-Identifier: MIT
 2 |     | pragma solidity ^0.8.0;
 3 |     | 
 4 |     | abstract contract BaseSetup {
 5 |     |     function setup() internal virtual;
 6 |     | }
 7 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/lib/chimera/src/BaseTargetFunctions.sol
 1 |     | // SPDX-License-Identifier: MIT
 2 |     | pragma solidity ^0.8.0;
 3 |     | 
 4 |     | import {BaseProperties} from "./BaseProperties.sol";
 5 |     | import {Asserts} from "./Asserts.sol";
 6 |     | 
 7 |     | abstract contract BaseTargetFunctions is BaseProperties, Asserts {}
 8 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/lib/chimera/src/CryticAsserts.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | import {Asserts} from "./Asserts.sol";
  5 |     | 
  6 |     | contract CryticAsserts is Asserts {
  7 |     |     event Log(string);
  8 |     | 
  9 | *   |     function gt(uint256 a, uint256 b, string memory reason) internal virtual override {
 10 | *   |         if (!(a > b)) {
 11 |     |             emit Log(reason);
 12 |     |             assert(false);
 13 |     |         }
 14 |     |     }
 15 |     | 
 16 | *   |     function gte(uint256 a, uint256 b, string memory reason) internal virtual override {
 17 | *   |         if (!(a >= b)) {
 18 | *   |             emit Log(reason);
 19 |     |             assert(false);
 20 |     |         }
 21 |     |     }
 22 |     | 
 23 |     |     function lt(uint256 a, uint256 b, string memory reason) internal virtual override {
 24 |     |         if (!(a < b)) {
 25 |     |             emit Log(reason);
 26 |     |             assert(false);
 27 |     |         }
 28 |     |     }
 29 |     | 
 30 | *   |     function lte(uint256 a, uint256 b, string memory reason) internal virtual override {
 31 | *   |         if (!(a <= b)) {
 32 | *   |             emit Log(reason);
 33 |     |             assert(false);
 34 |     |         }
 35 |     |     }
 36 |     | 
 37 | *   |     function eq(uint256 a, uint256 b, string memory reason) internal virtual override {
 38 | *   |         if (!(a == b)) {
 39 | *   |             emit Log(reason);
 40 | *   |             assert(false);
 41 |     |         }
 42 |     |     }
 43 |     | 
 44 | *   |     function t(bool b, string memory reason) internal virtual override {
 45 | *   |         if (!b) {
 46 | *   |             emit Log(reason);
 47 | *   |             assert(false);
 48 |     |         }
 49 |     |     }
 50 |     | 
 51 | *   |     function between(uint256 value, uint256 low, uint256 high) internal virtual override returns (uint256) {
 52 | *   |         if (value < low || value > high) {
 53 | *   |             uint256 ans = low + (value % (high - low + 1));
 54 | *   |             return ans;
 55 |     |         }
 56 | *   |         return value;
 57 |     |     }
 58 |     | 
 59 |     |     function between(int256 value, int256 low, int256 high) internal virtual override returns (int256) {
 60 |     |         if (value < low || value > high) {
 61 |     |             int256 range = high - low + 1;
 62 |     |             int256 clamped = (value - low) % (range);
 63 |     |             if (clamped < 0) clamped += range;
 64 |     |             int256 ans = low + clamped;
 65 |     |             return ans;
 66 |     |         }
 67 |     |         return value;
 68 |     |     }
 69 |     | 
 70 |     |     function precondition(bool p) internal virtual override {
 71 |     |         require(p);
 72 |     |     }
 73 |     | }
 74 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/lib/chimera/src/Hevm.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | // slither-disable-start shadowing-local
  5 |     | 
  6 |     | interface IHevm {
  7 |     |     // Set block.timestamp to newTimestamp
  8 |     |     function warp(uint256 newTimestamp) external;
  9 |     | 
 10 |     |     // Set block.number to newNumber
 11 |     |     function roll(uint256 newNumber) external;
 12 |     | 
 13 |     |     // Add the condition b to the assumption base for the current branch
 14 |     |     // This function is almost identical to require
 15 |     |     function assume(bool b) external;
 16 |     | 
 17 |     |     // Sets the eth balance of usr to amt
 18 |     |     function deal(address usr, uint256 amt) external;
 19 |     | 
 20 |     |     // Loads a storage slot from an address
 21 |     |     function load(address where, bytes32 slot) external returns (bytes32);
 22 |     | 
 23 |     |     // Stores a value to an address' storage slot
 24 |     |     function store(address where, bytes32 slot, bytes32 value) external;
 25 |     | 
 26 |     |     // Signs data (privateKey, digest) => (v, r, s)
 27 |     |     function sign(uint256 privateKey, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);
 28 |     | 
 29 |     |     // Gets address for a given private key
 30 |     |     function addr(uint256 privateKey) external returns (address addr);
 31 |     | 
 32 |     |     // Performs a foreign function call via terminal
 33 |     |     function ffi(string[] calldata inputs) external returns (bytes memory result);
 34 |     | 
 35 |     |     // Performs the next smart contract call with specified `msg.sender`
 36 |     |     function prank(address newSender) external;
 37 |     | 
 38 |     |     // Creates a new fork with the given endpoint and the latest block and returns the identifier of the fork
 39 |     |     function createFork(string calldata urlOrAlias) external returns (uint256);
 40 |     | 
 41 |     |     // Takes a fork identifier created by createFork and sets the corresponding forked state as active
 42 |     |     function selectFork(uint256 forkId) external;
 43 |     | 
 44 |     |     // Returns the identifier of the current fork
 45 |     |     function activeFork() external returns (uint256);
 46 |     | 
 47 |     |     // Labels the address in traces
 48 |     |     function label(address addr, string calldata label) external;
 49 |     | 
 50 |     |     /// Sets an address' code.
 51 |     |     function etch(address target, bytes calldata newRuntimeBytecode) external;
 52 |     | }
 53 |     | 
 54 | *   | IHevm constant vm = IHevm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
 55 |     | 
 56 |     | // slither-disable-end shadowing-local
 57 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/src/ActorManager.sol
  1 |     | // SPDX-License-Identifier: GPL-2.0
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | import {BaseSetup} from "@chimera/BaseSetup.sol";
  5 |     | import {vm} from "@chimera/Hevm.sol";
  6 |     | import {EnumerableSet} from "./EnumerableSet.sol";
  7 |     | 
  8 |     | /// @dev This is the source of truth for the actors being used in the test
  9 |     | /// @notice No actors should be used in the suite without being added here first
 10 |     | abstract contract ActorManager {
 11 |     |     using EnumerableSet for EnumerableSet.AddressSet;
 12 |     | 
 13 |     |     ///@notice The current actor being used
 14 |     |     address private _actor;
 15 |     | 
 16 |     |     ///@notice The list of all actors being used
 17 |     |     EnumerableSet.AddressSet private _actors;
 18 |     | 
 19 |     |     // If the current target is address(0) then it has not been setup yet and should revert
 20 |     |     error ActorNotSetup();
 21 |     |     // Do not allow duplicates
 22 |     |     error ActorExists();
 23 |     |     // If the actor does not exist
 24 |     |     error ActorNotAdded();
 25 |     |     // Do not allow the default actor
 26 |     |     error DefaultActor();
 27 |     | 
 28 |     |     /// @notice address(this) is the default actor
 29 |     |     constructor() {
 30 | *   |         _actors.add(address(this));
 31 | *   |         _actor = address(this);
 32 |     |     }
 33 |     | 
 34 |     |     /// @notice Returns the current active actor
 35 | *   |     function _getActor() internal view returns (address) {
 36 | *   |         return _actor;
 37 |     |     }
 38 |     | 
 39 |     |     /// @notice Returns all actors being used
 40 | *   |     function _getActors() internal view returns (address[] memory) {
 41 | *   |         return _actors.values();
 42 |     |     }
 43 |     | 
 44 |     |     /// @notice Adds an actor to the list of actors
 45 | *   |     function _addActor(address target) internal {
 46 | *   |         if (_actors.contains(target)) {
 47 |     |             revert ActorExists();
 48 |     |         }
 49 |     | 
 50 | *   |         if (target == address(this)) {
 51 |     |             revert DefaultActor();
 52 |     |         }
 53 |     | 
 54 | *   |         _actors.add(target);
 55 |     |     }
 56 |     | 
 57 |     |     /// @notice Removes an actor from the list of actors
 58 |     |     function _removeActor(address target) internal {
 59 |     |         if (!_actors.contains(target)) {
 60 |     |             revert ActorNotAdded();
 61 |     |         }
 62 |     | 
 63 |     |         if (target == address(this)) {
 64 |     |             revert DefaultActor();
 65 |     |         }
 66 |     | 
 67 |     |         _actors.remove(target);
 68 |     |     }
 69 |     | 
 70 |     |     /// @dev Expose this in the `TargetFunctions` contract to let the fuzzer switch actors
 71 |     |     ///   NOTE: We revert if the entropy is greater than the number of actors, for Halmos compatibility
 72 |     |     /// @dev This may reduce fuzzing performance if using multiple actors, if so add explicitly clamped handlers to ManagersTargets using the index of all added actors
 73 |     |     /// @notice Switches the current actor based on the entropy
 74 |     |     /// @param entropy The entropy to choose a random actor in the array for switching
 75 |     |     /// @return target The new active actor
 76 | *   |     function _switchActor(uint256 entropy) internal returns (address target) {
 77 | *   |         target = _actors.at(entropy);
 78 | *   |         _actor = target;
 79 |     |     }
 80 |     | }
 81 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/src/AssetManager.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {BaseSetup} from "@chimera/BaseSetup.sol";
   5 |     | import {vm} from "@chimera/Hevm.sol";
   6 |     | 
   7 |     | import {EnumerableSet} from "./EnumerableSet.sol";
   8 |     | import {MockERC20} from "./MockERC20.sol";
   9 |     | 
  10 |     | /// @dev Source of truth for the assets being used in the test
  11 |     | /// @notice No assets should be used in the suite without being added here first
  12 |     | abstract contract AssetManager {
  13 |     |     using EnumerableSet for EnumerableSet.AddressSet;
  14 |     | 
  15 |     |     /// @notice The current target for this set of variables
  16 |     |     address private __asset;
  17 |     | 
  18 |     |     /// @notice The list of all assets being used
  19 |     |     EnumerableSet.AddressSet private _assets;
  20 |     | 
  21 |     |     // If the current target is address(0) then it has not been setup yet and should revert
  22 |     |     error NotSetup();
  23 |     |     // Do not allow duplicates
  24 |     |     error Exists();
  25 |     |     // Enable only added assets
  26 |     |     error NotAdded();
  27 |     | 
  28 |     |     /// @notice Returns the current active asset
  29 | *   |     function _getAsset() internal view returns (address) {
  30 | *   |         if (__asset == address(0)) {
  31 |     |             revert NotSetup();
  32 |     |         }
  33 |     | 
  34 | *   |         return __asset;
  35 |     |     }
  36 |     | 
  37 |     |     /// @notice Returns all assets being used
  38 | *   |     function _getAssets() internal view returns (address[] memory) {
  39 | *   |         return _assets.values();
  40 |     |     }
  41 |     | 
  42 |     |     /// @notice Creates a new asset and adds it to the list of assets
  43 |     |     /// @param decimals The number of decimals for the asset
  44 |     |     /// @return The address of the new asset
  45 | *   |     function _newAsset(uint8 decimals) internal returns (address) {
  46 | *   |         address asset_ = address(new MockERC20("Test Token", "TST", decimals)); // If names get confusing, concatenate the decimals to the name
  47 | *   |         _addAsset(asset_);
  48 | *   |         __asset = asset_; // sets the asset as the current asset
  49 |     |         return asset_;
  50 |     |     }
  51 |     | 
  52 |     |     /// @notice Adds an asset to the list of assets
  53 |     |     /// @param target The address of the asset to add
  54 | *   |     function _addAsset(address target) internal {
  55 | *   |         if (_assets.contains(target)) {
  56 |     |             revert Exists();
  57 |     |         }
  58 |     | 
  59 | *   |         _assets.add(target);
  60 |     |     }
  61 |     | 
  62 |     |     /// @notice Removes an asset from the list of assets
  63 |     |     /// @param target The address of the asset to remove
  64 |     |     function _removeAsset(address target) internal {
  65 |     |         if (!_assets.contains(target)) {
  66 |     |             revert NotAdded();
  67 |     |         }
  68 |     | 
  69 |     |         _assets.remove(target);
  70 |     |     }
  71 |     | 
  72 |     |     /// @notice Switches the current asset based on the entropy
  73 |     |     ///   NOTE: We revert if the entropy is greater than the number of actors, for Halmos compatibility
  74 |     |     /// @param entropy The entropy to choose a random asset in the array for switching
  75 | *   |     function _switchAsset(uint256 entropy) internal {
  76 | *   |         address target = _assets.at(entropy);
  77 | *   |         __asset = target;
  78 |     |     }
  79 |     | 
  80 |     |     /// === Approve & Mint Asset === ///
  81 |     | 
  82 |     |     /// @notice Mint initial balance and approve allowances for the active asset
  83 |     |     /// @param actorsArray The array of actors to mint the asset to
  84 |     |     /// @param approvalArray The array of addresses to approve the asset to
  85 |     |     /// @param amount The amount of the asset to mint
  86 | *   |     function _finalizeAssetDeployment(address[] memory actorsArray, address[] memory approvalArray, uint256 amount)
  87 |     |         internal
  88 |     |     {
  89 | *   |         _mintAssetToAllActors(actorsArray, amount);
  90 | *   |         for (uint256 i; i < approvalArray.length; i++) {
  91 | *   |             _approveAssetToAddressForAllActors(actorsArray, approvalArray[i]);
  92 |     |         }
  93 |     |     }
  94 |     | 
  95 |     |     /// @notice Mint the asset to all actors
  96 |     |     /// @param actorsArray The array of actors to mint the asset to
  97 |     |     /// @param amount The amount of the asset to mint
  98 | *   |     function _mintAssetToAllActors(address[] memory actorsArray, uint256 amount) private {
  99 |     |         // mint all actors
 100 | *   |         address[] memory assets = _getAssets();
 101 | *   |         for (uint256 i; i < assets.length; i++) {
 102 | *   |             for (uint256 j; j < actorsArray.length; j++) {
 103 | *   |                 vm.prank(actorsArray[j]);
 104 | *   |                 MockERC20(assets[i]).mint(actorsArray[j], amount);
 105 |     |             }
 106 |     |         }
 107 |     |     }
 108 |     | 
 109 |     |     /// @notice Approve the asset to all actors
 110 |     |     /// @param actorsArray The array of actors to approve the asset from
 111 |     |     /// @param addressToApprove The address to approve the asset to
 112 | *   |     function _approveAssetToAddressForAllActors(address[] memory actorsArray, address addressToApprove) private {
 113 |     |         // approve to all actors
 114 | *   |         address[] memory assets = _getAssets();
 115 | *   |         for (uint256 i; i < assets.length; i++) {
 116 | *   |             for (uint256 j; j < actorsArray.length; j++) {
 117 | *   |                 vm.prank(actorsArray[j]);
 118 | *   |                 MockERC20(assets[i]).approve(addressToApprove, type(uint256).max);
 119 |     |             }
 120 |     |         }
 121 |     |     }
 122 |     | }
 123 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/src/EnumerableSet.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
   3 |     | // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
   4 |     | 
   5 |     | pragma solidity ^0.8.0;
   6 |     | 
   7 |     | /**
   8 |     |  * @dev Library for managing
   9 |     |  * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
  10 |     |  * types.
  11 |     |  *
  12 |     |  * Sets have the following properties:
  13 |     |  *
  14 |     |  * - Elements are added, removed, and checked for existence in constant time
  15 |     |  * (O(1)).
  16 |     |  * - Elements are enumerated in O(n). No guarantees are made on the ordering.
  17 |     |  *
  18 |     |  * ```solidity
  19 |     |  * contract Example {
  20 |     |  *     // Add the library methods
  21 |     |  *     using EnumerableSet for EnumerableSet.AddressSet;
  22 |     |  *
  23 |     |  *     // Declare a set state variable
  24 |     |  *     EnumerableSet.AddressSet private mySet;
  25 |     |  * }
  26 |     |  * ```
  27 |     |  *
  28 |     |  * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
  29 |     |  * and `uint256` (`UintSet`) are supported.
  30 |     |  *
  31 |     |  * [WARNING]
  32 |     |  * ====
  33 |     |  * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
  34 |     |  * unusable.
  35 |     |  * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
  36 |     |  *
  37 |     |  * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
  38 |     |  * array of EnumerableSet.
  39 |     |  * ====
  40 |     |  */
  41 |     | library EnumerableSet {
  42 |     |     // To implement this library for multiple types with as little code
  43 |     |     // repetition as possible, we write it in terms of a generic Set type with
  44 |     |     // bytes32 values.
  45 |     |     // The Set implementation uses private functions, and user-facing
  46 |     |     // implementations (such as AddressSet) are just wrappers around the
  47 |     |     // underlying Set.
  48 |     |     // This means that we can only create new EnumerableSets for types that fit
  49 |     |     // in bytes32.
  50 |     | 
  51 |     |     struct Set {
  52 |     |         // Storage of set values
  53 |     |         bytes32[] _values;
  54 |     |         // Position of the value in the `values` array, plus 1 because index 0
  55 |     |         // means a value is not in the set.
  56 |     |         mapping(bytes32 => uint256) _indexes;
  57 |     |     }
  58 |     | 
  59 |     |     /**
  60 |     |      * @dev Add a value to a set. O(1).
  61 |     |      *
  62 |     |      * Returns true if the value was added to the set, that is if it was not
  63 |     |      * already present.
  64 |     |      */
  65 | *   |     function _add(Set storage set, bytes32 value) private returns (bool) {
  66 | *   |         if (!_contains(set, value)) {
  67 | *   |             set._values.push(value);
  68 |     |             // The value is stored at length-1, but we add 1 to all indexes
  69 |     |             // and use 0 as a sentinel value
  70 | *   |             set._indexes[value] = set._values.length;
  71 | *   |             return true;
  72 |     |         } else {
  73 |     |             return false;
  74 |     |         }
  75 |     |     }
  76 |     | 
  77 |     |     /**
  78 |     |      * @dev Removes a value from a set. O(1).
  79 |     |      *
  80 |     |      * Returns true if the value was removed from the set, that is if it was
  81 |     |      * present.
  82 |     |      */
  83 |     |     function _remove(Set storage set, bytes32 value) private returns (bool) {
  84 |     |         // We read and store the value's index to prevent multiple reads from the same storage slot
  85 |     |         uint256 valueIndex = set._indexes[value];
  86 |     | 
  87 |     |         if (valueIndex != 0) {
  88 |     |             // Equivalent to contains(set, value)
  89 |     |             // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
  90 |     |             // the array, and then remove the last element (sometimes called as 'swap and pop').
  91 |     |             // This modifies the order of the array, as noted in {at}.
  92 |     | 
  93 |     |             uint256 toDeleteIndex = valueIndex - 1;
  94 |     |             uint256 lastIndex = set._values.length - 1;
  95 |     | 
  96 |     |             if (lastIndex != toDeleteIndex) {
  97 |     |                 bytes32 lastValue = set._values[lastIndex];
  98 |     | 
  99 |     |                 // Move the last value to the index where the value to delete is
 100 |     |                 set._values[toDeleteIndex] = lastValue;
 101 |     |                 // Update the index for the moved value
 102 |     |                 set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
 103 |     |             }
 104 |     | 
 105 |     |             // Delete the slot where the moved value was stored
 106 |     |             set._values.pop();
 107 |     | 
 108 |     |             // Delete the index for the deleted slot
 109 |     |             delete set._indexes[value];
 110 |     | 
 111 |     |             return true;
 112 |     |         } else {
 113 |     |             return false;
 114 |     |         }
 115 |     |     }
 116 |     | 
 117 |     |     /**
 118 |     |      * @dev Returns true if the value is in the set. O(1).
 119 |     |      */
 120 | *   |     function _contains(Set storage set, bytes32 value) private view returns (bool) {
 121 | *   |         return set._indexes[value] != 0;
 122 |     |     }
 123 |     | 
 124 |     |     /**
 125 |     |      * @dev Returns the number of values on the set. O(1).
 126 |     |      */
 127 | *   |     function _length(Set storage set) private view returns (uint256) {
 128 | *   |         return set._values.length;
 129 |     |     }
 130 |     | 
 131 |     |     /**
 132 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 133 |     |      *
 134 |     |      * Note that there are no guarantees on the ordering of values inside the
 135 |     |      * array, and it may change when more values are added or removed.
 136 |     |      *
 137 |     |      * Requirements:
 138 |     |      *
 139 |     |      * - `index` must be strictly less than {length}.
 140 |     |      */
 141 | *   |     function _at(Set storage set, uint256 index) private view returns (bytes32) {
 142 | *   |         return set._values[index];
 143 |     |     }
 144 |     | 
 145 |     |     /**
 146 |     |      * @dev Return the entire set in an array
 147 |     |      *
 148 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 149 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 150 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 151 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 152 |     |      */
 153 | *   |     function _values(Set storage set) private view returns (bytes32[] memory) {
 154 | *   |         return set._values;
 155 |     |     }
 156 |     | 
 157 |     |     // Bytes32Set
 158 |     | 
 159 |     |     struct Bytes32Set {
 160 |     |         Set _inner;
 161 |     |     }
 162 |     | 
 163 |     |     /**
 164 |     |      * @dev Add a value to a set. O(1).
 165 |     |      *
 166 |     |      * Returns true if the value was added to the set, that is if it was not
 167 |     |      * already present.
 168 |     |      */
 169 |     |     function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
 170 |     |         return _add(set._inner, value);
 171 |     |     }
 172 |     | 
 173 |     |     /**
 174 |     |      * @dev Removes a value from a set. O(1).
 175 |     |      *
 176 |     |      * Returns true if the value was removed from the set, that is if it was
 177 |     |      * present.
 178 |     |      */
 179 |     |     function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
 180 |     |         return _remove(set._inner, value);
 181 |     |     }
 182 |     | 
 183 |     |     /**
 184 |     |      * @dev Returns true if the value is in the set. O(1).
 185 |     |      */
 186 |     |     function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
 187 |     |         return _contains(set._inner, value);
 188 |     |     }
 189 |     | 
 190 |     |     /**
 191 |     |      * @dev Returns the number of values in the set. O(1).
 192 |     |      */
 193 |     |     function length(Bytes32Set storage set) internal view returns (uint256) {
 194 |     |         return _length(set._inner);
 195 |     |     }
 196 |     | 
 197 |     |     /**
 198 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 199 |     |      *
 200 |     |      * Note that there are no guarantees on the ordering of values inside the
 201 |     |      * array, and it may change when more values are added or removed.
 202 |     |      *
 203 |     |      * Requirements:
 204 |     |      *
 205 |     |      * - `index` must be strictly less than {length}.
 206 |     |      */
 207 |     |     function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
 208 |     |         return _at(set._inner, index);
 209 |     |     }
 210 |     | 
 211 |     |     /**
 212 |     |      * @dev Return the entire set in an array
 213 |     |      *
 214 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 215 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 216 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 217 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 218 |     |      */
 219 |     |     function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
 220 |     |         bytes32[] memory store = _values(set._inner);
 221 |     |         bytes32[] memory result;
 222 |     | 
 223 |     |         /// @solidity memory-safe-assembly
 224 |     |         assembly {
 225 |     |             result := store
 226 |     |         }
 227 |     | 
 228 |     |         return result;
 229 |     |     }
 230 |     | 
 231 |     |     // AddressSet
 232 |     | 
 233 |     |     struct AddressSet {
 234 |     |         Set _inner;
 235 |     |     }
 236 |     | 
 237 |     |     /**
 238 |     |      * @dev Add a value to a set. O(1).
 239 |     |      *
 240 |     |      * Returns true if the value was added to the set, that is if it was not
 241 |     |      * already present.
 242 |     |      */
 243 | *   |     function add(AddressSet storage set, address value) internal returns (bool) {
 244 | *   |         return _add(set._inner, bytes32(uint256(uint160(value))));
 245 |     |     }
 246 |     | 
 247 |     |     /**
 248 |     |      * @dev Removes a value from a set. O(1).
 249 |     |      *
 250 |     |      * Returns true if the value was removed from the set, that is if it was
 251 |     |      * present.
 252 |     |      */
 253 |     |     function remove(AddressSet storage set, address value) internal returns (bool) {
 254 |     |         return _remove(set._inner, bytes32(uint256(uint160(value))));
 255 |     |     }
 256 |     | 
 257 |     |     /**
 258 |     |      * @dev Returns true if the value is in the set. O(1).
 259 |     |      */
 260 | *   |     function contains(AddressSet storage set, address value) internal view returns (bool) {
 261 | *   |         return _contains(set._inner, bytes32(uint256(uint160(value))));
 262 |     |     }
 263 |     | 
 264 |     |     /**
 265 |     |      * @dev Returns the number of values in the set. O(1).
 266 |     |      */
 267 | *   |     function length(AddressSet storage set) internal view returns (uint256) {
 268 | *   |         return _length(set._inner);
 269 |     |     }
 270 |     | 
 271 |     |     /**
 272 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 273 |     |      *
 274 |     |      * Note that there are no guarantees on the ordering of values inside the
 275 |     |      * array, and it may change when more values are added or removed.
 276 |     |      *
 277 |     |      * Requirements:
 278 |     |      *
 279 |     |      * - `index` must be strictly less than {length}.
 280 |     |      */
 281 | *   |     function at(AddressSet storage set, uint256 index) internal view returns (address) {
 282 | *   |         return address(uint160(uint256(_at(set._inner, index))));
 283 |     |     }
 284 |     | 
 285 |     |     /**
 286 |     |      * @dev Return the entire set in an array
 287 |     |      *
 288 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 289 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 290 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 291 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 292 |     |      */
 293 | *   |     function values(AddressSet storage set) internal view returns (address[] memory) {
 294 | *   |         bytes32[] memory store = _values(set._inner);
 295 |     |         address[] memory result;
 296 |     | 
 297 |     |         /// @solidity memory-safe-assembly
 298 |     |         assembly {
 299 |     |             result := store
 300 |     |         }
 301 |     | 
 302 |     |         return result;
 303 |     |     }
 304 |     | 
 305 |     |     // UintSet
 306 |     | 
 307 |     |     struct UintSet {
 308 |     |         Set _inner;
 309 |     |     }
 310 |     | 
 311 |     |     /**
 312 |     |      * @dev Add a value to a set. O(1).
 313 |     |      *
 314 |     |      * Returns true if the value was added to the set, that is if it was not
 315 |     |      * already present.
 316 |     |      */
 317 |     |     function add(UintSet storage set, uint256 value) internal returns (bool) {
 318 |     |         return _add(set._inner, bytes32(value));
 319 |     |     }
 320 |     | 
 321 |     |     /**
 322 |     |      * @dev Removes a value from a set. O(1).
 323 |     |      *
 324 |     |      * Returns true if the value was removed from the set, that is if it was
 325 |     |      * present.
 326 |     |      */
 327 |     |     function remove(UintSet storage set, uint256 value) internal returns (bool) {
 328 |     |         return _remove(set._inner, bytes32(value));
 329 |     |     }
 330 |     | 
 331 |     |     /**
 332 |     |      * @dev Returns true if the value is in the set. O(1).
 333 |     |      */
 334 |     |     function contains(UintSet storage set, uint256 value) internal view returns (bool) {
 335 |     |         return _contains(set._inner, bytes32(value));
 336 |     |     }
 337 |     | 
 338 |     |     /**
 339 |     |      * @dev Returns the number of values in the set. O(1).
 340 |     |      */
 341 |     |     function length(UintSet storage set) internal view returns (uint256) {
 342 |     |         return _length(set._inner);
 343 |     |     }
 344 |     | 
 345 |     |     /**
 346 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 347 |     |      *
 348 |     |      * Note that there are no guarantees on the ordering of values inside the
 349 |     |      * array, and it may change when more values are added or removed.
 350 |     |      *
 351 |     |      * Requirements:
 352 |     |      *
 353 |     |      * - `index` must be strictly less than {length}.
 354 |     |      */
 355 |     |     function at(UintSet storage set, uint256 index) internal view returns (uint256) {
 356 |     |         return uint256(_at(set._inner, index));
 357 |     |     }
 358 |     | 
 359 |     |     /**
 360 |     |      * @dev Return the entire set in an array
 361 |     |      *
 362 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 363 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 364 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 365 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 366 |     |      */
 367 |     |     function values(UintSet storage set) internal view returns (uint256[] memory) {
 368 |     |         bytes32[] memory store = _values(set._inner);
 369 |     |         uint256[] memory result;
 370 |     | 
 371 |     |         /// @solidity memory-safe-assembly
 372 |     |         assembly {
 373 |     |             result := store
 374 |     |         }
 375 |     | 
 376 |     |         return result;
 377 |     |     }
 378 |     | }
 379 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/src/MockERC20.sol
   1 |     | // SPDX-License-Identifier: AGPL-3.0-only
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
   5 |     | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
   6 |     | /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
   7 |     | /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
   8 |     | abstract contract ERC20 {
   9 |     |     /*//////////////////////////////////////////////////////////////
  10 |     |                                  ERRORS
  11 |     |     //////////////////////////////////////////////////////////////*/
  12 |     | 
  13 |     |     /// @notice Thrown when attempting to transfer more tokens than available balance
  14 |     |     error InsufficientBalance(address from, uint256 balance, uint256 amount);
  15 |     | 
  16 |     |     /// @notice Thrown when attempting to transfer more tokens than allowed
  17 |     |     error InsufficientAllowance(address owner, address spender, uint256 allowance, uint256 amount);
  18 |     | 
  19 |     |     /// @notice Thrown when minting would cause overflow
  20 |     |     error MintOverflow(uint256 currentSupply, uint256 amount);
  21 |     | 
  22 |     |     /*//////////////////////////////////////////////////////////////
  23 |     |                                  EVENTS
  24 |     |     //////////////////////////////////////////////////////////////*/
  25 |     | 
  26 |     |     event Transfer(address indexed from, address indexed to, uint256 amount);
  27 |     | 
  28 |     |     event Approval(address indexed owner, address indexed spender, uint256 amount);
  29 |     | 
  30 |     |     /*//////////////////////////////////////////////////////////////
  31 |     |                             METADATA STORAGE
  32 |     |     //////////////////////////////////////////////////////////////*/
  33 |     | 
  34 | *   |     string public name;
  35 |     | 
  36 |     |     string public symbol;
  37 |     | 
  38 | *   |     uint8 public immutable decimals;
  39 |     | 
  40 |     |     /*//////////////////////////////////////////////////////////////
  41 |     |                               ERC20 STORAGE
  42 |     |     //////////////////////////////////////////////////////////////*/
  43 |     | 
  44 | *   |     uint256 public totalSupply;
  45 |     | 
  46 | *   |     mapping(address => uint256) public balanceOf;
  47 |     | 
  48 |     |     mapping(address => mapping(address => uint256)) public allowance;
  49 |     | 
  50 |     |     /*//////////////////////////////////////////////////////////////
  51 |     |                             EIP-2612 STORAGE
  52 |     |     //////////////////////////////////////////////////////////////*/
  53 |     | 
  54 |     |     uint256 internal immutable INITIAL_CHAIN_ID;
  55 |     | 
  56 |     |     bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
  57 |     | 
  58 |     |     mapping(address => uint256) public nonces;
  59 |     | 
  60 |     |     /*//////////////////////////////////////////////////////////////
  61 |     |                                CONSTRUCTOR
  62 |     |     //////////////////////////////////////////////////////////////*/
  63 |     | 
  64 |     |     constructor(string memory _name, string memory _symbol, uint8 _decimals) {
  65 | *   |         name = _name;
  66 | *   |         symbol = _symbol;
  67 | *   |         decimals = _decimals;
  68 |     | 
  69 | *   |         INITIAL_CHAIN_ID = block.chainid;
  70 | *   |         INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
  71 |     |     }
  72 |     | 
  73 |     |     /*//////////////////////////////////////////////////////////////
  74 |     |                                ERC20 LOGIC
  75 |     |     //////////////////////////////////////////////////////////////*/
  76 |     | 
  77 | *   |     function approve(address spender, uint256 amount) public virtual returns (bool) {
  78 | *   |         allowance[msg.sender][spender] = amount;
  79 |     | 
  80 | *   |         emit Approval(msg.sender, spender, amount);
  81 |     | 
  82 | *   |         return true;
  83 |     |     }
  84 |     | 
  85 | *   |     function transfer(address to, uint256 amount) public virtual returns (bool) {
  86 | *   |         uint256 fromBalance = balanceOf[msg.sender];
  87 | *   |         if (fromBalance < amount) revert InsufficientBalance(msg.sender, fromBalance, amount);
  88 |     | 
  89 | *   |         balanceOf[msg.sender] = fromBalance - amount;
  90 |     | 
  91 |     |         // Cannot overflow because the sum of all user
  92 |     |         // balances can't exceed the max uint256 value.
  93 |     |         unchecked {
  94 | *   |             balanceOf[to] += amount;
  95 |     |         }
  96 |     | 
  97 | *   |         emit Transfer(msg.sender, to, amount);
  98 |     | 
  99 | *   |         return true;
 100 |     |     }
 101 |     | 
 102 | *   |     function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
 103 | *   |         uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
 104 | *   |         uint256 fromBalance = balanceOf[from];
 105 |     | 
 106 | *   |         if (allowed != type(uint256).max) {
 107 | *   |             if (allowed < amount) revert InsufficientAllowance(from, msg.sender, allowed, amount);
 108 | *   |             allowance[from][msg.sender] = allowed - amount;
 109 |     |         }
 110 |     | 
 111 | *   |         if (fromBalance < amount) revert InsufficientBalance(from, fromBalance, amount);
 112 | *   |         balanceOf[from] = fromBalance - amount;
 113 |     | 
 114 |     |         // Cannot overflow because the sum of all user
 115 |     |         // balances can't exceed the max uint256 value.
 116 |     |         unchecked {
 117 | *   |             balanceOf[to] += amount;
 118 |     |         }
 119 |     | 
 120 | *   |         emit Transfer(from, to, amount);
 121 |     | 
 122 | *   |         return true;
 123 |     |     }
 124 |     | 
 125 |     |     /*//////////////////////////////////////////////////////////////
 126 |     |                              EIP-2612 LOGIC
 127 |     |     //////////////////////////////////////////////////////////////*/
 128 |     | 
 129 |     |     function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
 130 |     |         public
 131 |     |         virtual
 132 |     |     {
 133 |     |         require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
 134 |     | 
 135 |     |         // Unchecked because the only math done is incrementing
 136 |     |         // the owner's nonce which cannot realistically overflow.
 137 |     |         unchecked {
 138 |     |             address recoveredAddress = ecrecover(
 139 |     |                 keccak256(
 140 |     |                     abi.encodePacked(
 141 |     |                         "\x19\x01",
 142 |     |                         DOMAIN_SEPARATOR(),
 143 |     |                         keccak256(
 144 |     |                             abi.encode(
 145 |     |                                 keccak256(
 146 |     |                                     "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
 147 |     |                                 ),
 148 |     |                                 owner,
 149 |     |                                 spender,
 150 |     |                                 value,
 151 |     |                                 nonces[owner]++,
 152 |     |                                 deadline
 153 |     |                             )
 154 |     |                         )
 155 |     |                     )
 156 |     |                 ),
 157 |     |                 v,
 158 |     |                 r,
 159 |     |                 s
 160 |     |             );
 161 |     | 
 162 |     |             require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
 163 |     | 
 164 |     |             allowance[recoveredAddress][spender] = value;
 165 |     |         }
 166 |     | 
 167 |     |         emit Approval(owner, spender, value);
 168 |     |     }
 169 |     | 
 170 |     |     function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
 171 |     |         return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
 172 |     |     }
 173 |     | 
 174 | *   |     function computeDomainSeparator() internal view virtual returns (bytes32) {
 175 | *   |         return keccak256(
 176 | *   |             abi.encode(
 177 | *   |                 keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
 178 | *   |                 keccak256(bytes(name)),
 179 | *   |                 keccak256("1"),
 180 | *   |                 block.chainid,
 181 | *   |                 address(this)
 182 |     |             )
 183 |     |         );
 184 |     |     }
 185 |     | 
 186 |     |     /*//////////////////////////////////////////////////////////////
 187 |     |                         INTERNAL MINT/BURN LOGIC
 188 |     |     //////////////////////////////////////////////////////////////*/
 189 |     | 
 190 | *   |     function _mint(address to, uint256 amount) internal virtual {
 191 | *   |         uint256 newTotalSupply = totalSupply + amount;
 192 | *   |         if (newTotalSupply < totalSupply) revert MintOverflow(totalSupply, amount);
 193 | *   |         totalSupply = newTotalSupply;
 194 |     | 
 195 |     |         // Cannot overflow because the sum of all user
 196 |     |         // balances can't exceed the max uint256 value.
 197 |     |         unchecked {
 198 | *   |             balanceOf[to] += amount;
 199 |     |         }
 200 |     | 
 201 | *   |         emit Transfer(address(0), to, amount);
 202 |     |     }
 203 |     | 
 204 | *   |     function _burn(address from, uint256 amount) internal virtual {
 205 | *   |         uint256 fromBalance = balanceOf[from];
 206 | *   |         if (fromBalance < amount) revert InsufficientBalance(from, fromBalance, amount);
 207 |     | 
 208 | *   |         balanceOf[from] = fromBalance - amount;
 209 |     | 
 210 |     |         // Cannot underflow because a user's balance
 211 |     |         // will never be larger than the total supply.
 212 |     |         unchecked {
 213 | *   |             totalSupply -= amount;
 214 |     |         }
 215 |     | 
 216 | *   |         emit Transfer(from, address(0), amount);
 217 |     |     }
 218 |     | }
 219 |     | 
 220 | *   | contract MockERC20 is ERC20 {
 221 | *   |     constructor(string memory _name, string memory _symbol, uint8 _decimals) ERC20(_name, _symbol, _decimals) {}
 222 |     | 
 223 | *   |     function mint(address to, uint256 value) public virtual {
 224 | *   |         _mint(to, value);
 225 |     |     }
 226 |     | 
 227 |     |     function burn(address from, uint256 value) public virtual {
 228 |     |         _burn(from, value);
 229 |     |     }
 230 |     | }
 231 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/src/Panic.sol
  1 |     | // SPDX-License-Identifier: GPL-2.0
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | library Panic {
  5 |     |     // compiler panics
  6 |     |     string constant assertionPanic = "Panic(1)";
  7 |     |     string constant arithmeticPanic = "Panic(17)";
  8 |     |     string constant divisionPanic = "Panic(18)";
  9 |     |     string constant enumPanic = "Panic(33)";
 10 |     |     string constant arrayPanic = "Panic(34)";
 11 |     |     string constant emptyArrayPanic = "Panic(49)";
 12 |     |     string constant outOfBoundsPanic = "Panic(50)";
 13 |     |     string constant memoryPanic = "Panic(65)";
 14 |     |     string constant functionPanic = "Panic(81)";
 15 |     | }
 16 |     | 

/opt/scfuzzbench/work/target/lib/setup-helpers/src/Utils.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {Panic} from "./Panic.sol";
   5 |     | 
   6 |     | contract Utils {
   7 |     |     /// @dev check if the error returned from a call is the same as the expected error
   8 |     |     /// @param err the error returned from a call
   9 |     |     /// @param expected the expected error
  10 |     |     /// @return true if the error is the same as the expected error, false otherwise
  11 | *   |     function checkError(bytes memory err, string memory expected) internal pure returns (bool) {
  12 | *   |         (string memory revertMsg, bool customError) = _getRevertMsg(err);
  13 |     | 
  14 | *   |         bytes32 errorBytes;
  15 | *   |         bytes32 expectedBytes;
  16 |     | 
  17 | *   |         if (customError) {
  18 |     |             // Custom error returns the keccak256 hash of the error, so don't need to hash it again
  19 | *   |             errorBytes = bytes32(abi.encodePacked(revertMsg, bytes28(0)));
  20 | *   |             expectedBytes = bytes4(keccak256(abi.encodePacked(expected)));
  21 |     |         } else {
  22 | *   |             errorBytes = keccak256(abi.encodePacked(revertMsg));
  23 | *   |             expectedBytes = keccak256(abi.encodePacked(expected));
  24 |     |         }
  25 |     | 
  26 |     |         // Check if error contains expected string
  27 | *   |         return errorBytes == expectedBytes;
  28 |     |     }
  29 |     | 
  30 |     |     /// @dev get the revert message from a call
  31 |     |     /// @notice based on https://ethereum.stackexchange.com/a/83577
  32 |     |     /// @param returnData the return data from a call
  33 |     |     /// @return the revert message and a boolean indicating if it's a custom error
  34 | *   |     function _getRevertMsg(bytes memory returnData) internal pure returns (string memory, bool) {
  35 |     |         // If the returnData length is 0, then the transaction failed silently (without a revert message)
  36 | *   |         if (returnData.length == 0) return ("", false);
  37 |     | 
  38 |     |         // 1. Panic(uint256)
  39 |     |         // Check that the data has the right size: 4 bytes for signature + 32 bytes for panic code
  40 | *   |         if (returnData.length == 4 + 32) {
  41 |     |             // Check that the data starts with the Panic signature
  42 | *   |             bool panic = _checkIfPanic(returnData);
  43 |     | 
  44 | *   |             if (panic) {
  45 | *   |                 return _getPanicCode(returnData);
  46 |     |             }
  47 |     |         }
  48 |     | 
  49 |     |         // Get the error selector from returnData
  50 | *   |         bytes4 errorSelector = _getErrorSelector(returnData);
  51 |     | 
  52 |     |         // 2. Error(string) - If it's a standard revert string
  53 | *   |         bytes4 errorStringSelector = bytes4(keccak256("Error(string)")); // Get the standard Error(string) selector
  54 |     | 
  55 | *   |         if (errorSelector == errorStringSelector) {
  56 |     |             assembly {
  57 |     |                 // slice the sighash of the error so we can decode the string
  58 |     |                 returnData := add(returnData, 0x04)
  59 |     |             }
  60 |     |             return (abi.decode(returnData, (string)), false);
  61 |     |         }
  62 |     | 
  63 |     |         // 3. Custom error - Return the custom error selector as a string
  64 | *   |         return (string(abi.encodePacked(errorSelector)), true);
  65 |     |     }
  66 |     | 
  67 | *   |     function _checkIfPanic(bytes memory returnData) internal pure returns (bool) {
  68 | *   |         bytes4 panicSignature = bytes4(keccak256(bytes("Panic(uint256)")));
  69 |     | 
  70 | *   |         for (uint256 i = 0; i < 4; i++) {
  71 | *   |             if (returnData[i] != panicSignature[i]) {
  72 |     |                 return false;
  73 |     |             }
  74 |     |         }
  75 |     | 
  76 | *   |         return true;
  77 |     |     }
  78 |     | 
  79 | *   |     function _getPanicCode(bytes memory returnData) internal pure returns (string memory, bool) {
  80 |     |         uint256 panicCode;
  81 | *   |         for (uint256 i = 4; i < 36; i++) {
  82 | *   |             panicCode = panicCode << 8;
  83 | *   |             panicCode |= uint8(returnData[i]);
  84 |     |         }
  85 |     | 
  86 |     |         // Convert the panic code into its string representation
  87 | *   |         if (panicCode == 1) {
  88 |     |             // call assert with an argument that evaluates to false
  89 |     |             return (Panic.assertionPanic, false);
  90 | *   |         } else if (panicCode == 17) {
  91 |     |             // arithmetic operation results in underflow or overflow
  92 | *   |             return (Panic.arithmeticPanic, false);
  93 |     |         } else if (panicCode == 18) {
  94 |     |             // division or modulo by zero
  95 |     |             return (Panic.divisionPanic, false);
  96 |     |         } else if (panicCode == 33) {
  97 |     |             // converting a value that's too big or negative into an enum type
  98 |     |             return (Panic.enumPanic, false);
  99 |     |         } else if (panicCode == 34) {
 100 |     |             // access a storage byte array that is incorrectly encoded
 101 |     |             return (Panic.arrayPanic, false);
 102 |     |         } else if (panicCode == 49) {
 103 |     |             // call .pop() on an empty array
 104 |     |             return (Panic.emptyArrayPanic, false);
 105 |     |         } else if (panicCode == 50) {
 106 |     |             // array access out of bounds
 107 |     |             return (Panic.outOfBoundsPanic, false);
 108 |     |         } else if (panicCode == 65) {
 109 |     |             // allocate too much memory or create an array that is too large
 110 |     |             return (Panic.memoryPanic, false);
 111 |     |         } else if (panicCode == 81) {
 112 |     |             // call a zero-initialized variable of internal function type
 113 |     |             return (Panic.functionPanic, false);
 114 |     |         }
 115 |     | 
 116 |     |         return ("Undefined panic code", false);
 117 |     |     }
 118 |     | 
 119 | *   |     function _getErrorSelector(bytes memory returnData) internal pure returns (bytes4 errorSelector) {
 120 |     |         assembly {
 121 | *   |             errorSelector := mload(add(returnData, 0x20))
 122 |     |         }
 123 |     |         return errorSelector;
 124 |     |     }
 125 |     | }
 126 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/modulekit/src/accounts/common/interfaces/IERC7579Account.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | pragma solidity >=0.8.23 <0.9.0;
   3 |     | 
   4 |     | /* solhint-disable no-unused-import */
   5 |     | 
   6 |     | // Types
   7 |     | import { CallType, ExecType, ModeCode } from "../lib/ModeLib.sol";
   8 |     | 
   9 |     | // Structs
  10 |     | struct Execution {
  11 |     |     address target;
  12 |     |     uint256 value;
  13 |     |     bytes callData;
  14 |     | }
  15 |     | 
  16 |     | interface IERC7579Account {
  17 |     |     event ModuleInstalled(uint256 moduleTypeId, address module);
  18 |     |     event ModuleUninstalled(uint256 moduleTypeId, address module);
  19 |     | 
  20 |     |     /**
  21 |     |      * @dev Executes a transaction on behalf of the account.
  22 |     |      *         This function is intended to be called by ERC-4337 EntryPoint.sol
  23 |     |      * @dev Ensure adequate authorization control: i.e. onlyEntryPointOrSelf
  24 |     |      *
  25 |     |      * @dev MSA MUST implement this function signature.
  26 |     |      * If a mode is requested that is not supported by the Account, it MUST revert
  27 |     |      * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details
  28 |     |      * @param executionCalldata The encoded execution call data
  29 |     |      */
  30 |     |     function execute(ModeCode mode, bytes calldata executionCalldata) external payable;
  31 |     | 
  32 |     |     /**
  33 |     |      * @dev Executes a transaction on behalf of the account.
  34 |     |      *         This function is intended to be called by Executor Modules
  35 |     |      * @dev Ensure adequate authorization control: i.e. onlyExecutorModule
  36 |     |      *
  37 |     |      * @dev MSA MUST implement this function signature.
  38 |     |      * If a mode is requested that is not supported by the Account, it MUST revert
  39 |     |      * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details
  40 |     |      * @param executionCalldata The encoded execution call data
  41 |     |      */
  42 |     |     function executeFromExecutor(
  43 |     |         ModeCode mode,
  44 |     |         bytes calldata executionCalldata
  45 |     |     )
  46 |     |         external
  47 |     |         payable
  48 |     |         returns (bytes[] memory returnData);
  49 |     | 
  50 |     |     /**
  51 |     |      * @dev ERC-1271 isValidSignature
  52 |     |      *         This function is intended to be used to validate a smart account signature
  53 |     |      * and may forward the call to a validator module
  54 |     |      *
  55 |     |      * @param hash The hash of the data that is signed
  56 |     |      * @param data The data that is signed
  57 |     |      */
  58 |     |     function isValidSignature(bytes32 hash, bytes calldata data) external view returns (bytes4);
  59 |     | 
  60 |     |     /**
  61 |     |      * @dev installs a Module of a certain type on the smart account
  62 |     |      * @dev Implement Authorization control of your chosing
  63 |     |      * @param moduleTypeId the module type ID according the ERC-7579 spec
  64 |     |      * @param module the module address
  65 |     |      * @param initData arbitrary data that may be required on the module during `onInstall`
  66 |     |      * initialization.
  67 |     |      */
  68 |     |     function installModule(
  69 |     |         uint256 moduleTypeId,
  70 |     |         address module,
  71 |     |         bytes calldata initData
  72 |     |     )
  73 |     |         external
  74 |     |         payable;
  75 |     | 
  76 |     |     /**
  77 |     |      * @dev uninstalls a Module of a certain type on the smart account
  78 |     |      * @dev Implement Authorization control of your chosing
  79 |     |      * @param moduleTypeId the module type ID according the ERC-7579 spec
  80 |     |      * @param module the module address
  81 |     |      * @param deInitData arbitrary data that may be required on the module during `onUninstall`
  82 |     |      * de-initialization.
  83 |     |      */
  84 |     |     function uninstallModule(
  85 |     |         uint256 moduleTypeId,
  86 |     |         address module,
  87 |     |         bytes calldata deInitData
  88 |     |     )
  89 |     |         external
  90 |     |         payable;
  91 |     | 
  92 |     |     /**
  93 |     |      * Function to check if the account supports a certain CallType or ExecType (see ModeLib.sol)
  94 |     |      * @param encodedMode the encoded mode
  95 |     |      */
  96 |     |     function supportsExecutionMode(ModeCode encodedMode) external view returns (bool);
  97 |     | 
  98 |     |     /**
  99 |     |      * Function to check if the account supports installation of a certain module type Id
 100 |     |      * @param moduleTypeId the module type ID according the ERC-7579 spec
 101 |     |      */
 102 |     |     function supportsModule(uint256 moduleTypeId) external view returns (bool);
 103 |     | 
 104 |     |     /**
 105 |     |      * Function to check if the account has a certain module installed
 106 |     |      * @param moduleTypeId the module type ID according the ERC-7579 spec
 107 |     |      *      Note: keep in mind that some contracts can be multiple module types at the same time. It
 108 |     |      *            thus may be necessary to query multiple module types
 109 |     |      * @param module the module address
 110 |     |      * @param additionalContext additional context data that the smart account may interpret to
 111 |     |      *                          identifiy conditions under which the module is installed.
 112 |     |      *                          usually this is not necessary, but for some special hooks that
 113 |     |      *                          are stored in mappings, this param might be needed
 114 |     |      */
 115 |     |     function isModuleInstalled(
 116 |     |         uint256 moduleTypeId,
 117 |     |         address module,
 118 |     |         bytes calldata additionalContext
 119 |     |     )
 120 |     |         external
 121 |     |         view
 122 |     |         returns (bool);
 123 |     | 
 124 |     |     /**
 125 |     |      * @dev Returns the account id of the smart account
 126 |     |      * @return accountImplementationId the account id of the smart account
 127 |     |      * the accountId should be structured like so:
 128 |     |      *        "vendorname.accountname.semver"
 129 |     |      */
 130 |     |     function accountId() external view returns (string memory accountImplementationId);
 131 |     | }
 132 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/modulekit/src/accounts/common/lib/ModeLib.sol
   1 |     | // SPDX-License-Identifier: GPL-3.0
   2 |     | pragma solidity >=0.8.0 <0.9.0;
   3 |     | 
   4 |     | /**
   5 |     |  * @title ModeLib
   6 |     |  * @author rhinestone | zeroknots.eth, Konrad Kopp (@kopy-kat)
   7 |     |  * To allow smart accounts to be very simple, but allow for more complex execution, A custom mode
   8 |     |  * encoding is used.
   9 |     |  *    Function Signature of execute function:
  10 |     |  *           function execute(ModeCode mode, bytes calldata executionCalldata) external payable;
  11 |     |  * This allows for a single bytes32 to be used to encode the execution mode, calltype, execType and
  12 |     |  * context.
  13 |     |  * NOTE: Simple Account implementations only have to scope for the most significant byte. Account  that
  14 |     |  * implement
  15 |     |  * more complex execution modes may use the entire bytes32.
  16 |     |  *
  17 |     |  * |--------------------------------------------------------------------|
  18 |     |  * | CALLTYPE  | EXECTYPE  |   UNUSED   | ModeSelector  |  ModePayload  |
  19 |     |  * |--------------------------------------------------------------------|
  20 |     |  * | 1 byte    | 1 byte    |   4 bytes  | 4 bytes       |   22 bytes    |
  21 |     |  * |--------------------------------------------------------------------|
  22 |     |  *
  23 |     |  * CALLTYPE: 1 byte
  24 |     |  * CallType is used to determine how the executeCalldata paramter of the execute function has to be
  25 |     |  * decoded.
  26 |     |  * It can be either single, batch or delegatecall. In the future different calls could be added.
  27 |     |  * CALLTYPE can be used by a validation module to determine how to decode <userOp.callData[36:]>.
  28 |     |  *
  29 |     |  * EXECTYPE: 1 byte
  30 |     |  * ExecType is used to determine how the account should handle the execution.
  31 |     |  * It can indicate if the execution should revert on failure or continue execution.
  32 |     |  * In the future more execution modes may be added.
  33 |     |  * Default Behavior (EXECTYPE = 0x00) is to revert on a single failed execution. If one execution in
  34 |     |  * a batch fails, the entire batch is reverted
  35 |     |  *
  36 |     |  * UNUSED: 4 bytes
  37 |     |  * Unused bytes are reserved for future use.
  38 |     |  *
  39 |     |  * ModeSelector: bytes4
  40 |     |  * The "optional" mode selector can be used by account vendors, to implement custom behavior in
  41 |     |  * their accounts.
  42 |     |  * the way a ModeSelector is to be calculated is bytes4(keccak256("vendorname.featurename"))
  43 |     |  * this is to prevent collisions between different vendors, while allowing innovation and the
  44 |     |  * development of new features without coordination between ERC-7579 implementing accounts
  45 |     |  *
  46 |     |  * ModePayload: 22 bytes
  47 |     |  * Mode payload is used to pass additional data to the smart account execution, this may be
  48 |     |  * interpreted depending on the ModeSelector
  49 |     |  *
  50 |     |  * ExecutionCallData: n bytes
  51 |     |  * single, delegatecall or batch exec abi.encoded as bytes
  52 |     |  */
  53 |     | 
  54 |     | // Custom type for improved developer experience
  55 |     | type ModeCode is bytes32;
  56 |     | 
  57 |     | type CallType is bytes1;
  58 |     | 
  59 |     | type ExecType is bytes1;
  60 |     | 
  61 |     | type ModeSelector is bytes4;
  62 |     | 
  63 |     | type ModePayload is bytes22;
  64 |     | 
  65 |     | // Default CallType
  66 |     | CallType constant CALLTYPE_SINGLE = CallType.wrap(0x00);
  67 |     | // Batched CallType
  68 |     | CallType constant CALLTYPE_BATCH = CallType.wrap(0x01);
  69 |     | CallType constant CALLTYPE_STATIC = CallType.wrap(0xFE);
  70 |     | // @dev Implementing delegatecall is OPTIONAL!
  71 |     | // implement delegatecall with extreme care.
  72 |     | CallType constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF);
  73 |     | 
  74 |     | // @dev default behavior is to revert on failure
  75 |     | // To allow very simple accounts to use mode encoding, the default behavior is to revert on failure
  76 |     | // Since this is value 0x00, no additional encoding is required for simple accounts
  77 |     | ExecType constant EXECTYPE_DEFAULT = ExecType.wrap(0x00);
  78 |     | // @dev account may elect to change execution behavior. For example "try exec" / "allow fail"
  79 |     | ExecType constant EXECTYPE_TRY = ExecType.wrap(0x01);
  80 |     | 
  81 |     | ModeSelector constant MODE_DEFAULT = ModeSelector.wrap(bytes4(0x00000000));
  82 |     | // Example declaration of a custom mode selector
  83 |     | ModeSelector constant MODE_OFFSET = ModeSelector.wrap(bytes4(keccak256("default.mode.offset")));
  84 |     | 
  85 |     | /**
  86 |     |  * @dev ModeLib is a helper library to encode/decode ModeCodes
  87 |     |  */
  88 |     | library ModeLib {
  89 |     |     function decode(ModeCode mode)
  90 |     |         internal
  91 |     |         pure
  92 |     |         returns (
  93 |     |             CallType _calltype,
  94 |     |             ExecType _execType,
  95 |     |             ModeSelector _modeSelector,
  96 |     |             ModePayload _modePayload
  97 |     |         )
  98 |     |     {
  99 |     |         // solhint-disable-next-line no-inline-assembly
 100 |     |         assembly {
 101 |     |             _calltype := mode
 102 |     |             _execType := shl(8, mode)
 103 |     |             _modeSelector := shl(48, mode)
 104 |     |             _modePayload := shl(80, mode)
 105 |     |         }
 106 |     |     }
 107 |     | 
 108 |     |     function encode(
 109 |     |         CallType callType,
 110 |     |         ExecType execType,
 111 |     |         ModeSelector mode,
 112 |     |         ModePayload payload
 113 |     |     )
 114 |     |         internal
 115 |     |         pure
 116 |     |         returns (ModeCode)
 117 |     |     {
 118 |     |         return ModeCode.wrap(
 119 |     |             bytes32(
 120 |     |                 abi.encodePacked(callType, execType, bytes4(0), ModeSelector.unwrap(mode), payload)
 121 |     |             )
 122 |     |         );
 123 |     |     }
 124 |     | 
 125 |     |     function encodeSimpleBatch() internal pure returns (ModeCode mode) {
 126 |     |         mode = encode(CALLTYPE_BATCH, EXECTYPE_DEFAULT, MODE_DEFAULT, ModePayload.wrap(0x00));
 127 |     |     }
 128 |     | 
 129 |     |     function encodeSimpleSingle() internal pure returns (ModeCode mode) {
 130 |     |         mode = encode(CALLTYPE_SINGLE, EXECTYPE_DEFAULT, MODE_DEFAULT, ModePayload.wrap(0x00));
 131 |     |     }
 132 |     | 
 133 |     |     function getCallType(ModeCode mode) internal pure returns (CallType calltype) {
 134 |     |         // solhint-disable-next-line no-inline-assembly
 135 |     |         assembly {
 136 |     |             calltype := mode
 137 |     |         }
 138 |     |     }
 139 |     | }
 140 |     | 
 141 |     | using { eqModeSelector as == } for ModeSelector global;
 142 |     | using { eqCallType as == } for CallType global;
 143 |     | using { neqCallType as != } for CallType global;
 144 |     | using { eqExecType as == } for ExecType global;
 145 |     | 
 146 |     | function eqCallType(CallType a, CallType b) pure returns (bool) {
 147 |     |     return CallType.unwrap(a) == CallType.unwrap(b);
 148 |     | }
 149 |     | 
 150 |     | function neqCallType(CallType a, CallType b) pure returns (bool) {
 151 |     |     return CallType.unwrap(a) == CallType.unwrap(b);
 152 |     | }
 153 |     | 
 154 |     | function eqExecType(ExecType a, ExecType b) pure returns (bool) {
 155 |     |     return ExecType.unwrap(a) == ExecType.unwrap(b);
 156 |     | }
 157 |     | 
 158 |     | function eqModeSelector(ModeSelector a, ModeSelector b) pure returns (bool) {
 159 |     |     return ModeSelector.unwrap(a) == ModeSelector.unwrap(b);
 160 |     | }
 161 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/modulekit/src/accounts/erc7579/lib/ExecutionLib.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | pragma solidity >=0.8.23 <0.9.0;
  3 |     | 
  4 |     | // Types
  5 |     | import { Execution } from "../../common/interfaces/IERC7579Account.sol";
  6 |     | 
  7 |     | /**
  8 |     |  * Helper Library for decoding Execution calldata
  9 |     |  * malloc for memory allocation is bad for gas. use this assembly instead
 10 |     |  */
 11 |     | library ExecutionLib {
 12 |     |     error ERC7579DecodingError();
 13 |     | 
 14 |     |     /**
 15 |     |      * @notice Decode a batch of `Execution` executionBatch from a `bytes` calldata.
 16 |     |      * @dev code is copied from solady's LibERC7579.sol
 17 |     |      * https://github.com/Vectorized/solady/blob/740812cedc9a1fc11e17cb3d4569744367dedf19/src/accounts/LibERC7579.sol#L146
 18 |     |      *      Credits to Vectorized and the Solady Team
 19 |     |      */
 20 |     |     function decodeBatch(bytes calldata executionCalldata)
 21 |     |         internal
 22 |     |         pure
 23 |     |         returns (Execution[] calldata executionBatch)
 24 |     |     {
 25 |     |         /// @solidity memory-safe-assembly
 26 |     |         assembly {
 27 |     |             let u := calldataload(executionCalldata.offset)
 28 |     |             let s := add(executionCalldata.offset, u)
 29 |     |             let e := sub(add(executionCalldata.offset, executionCalldata.length), 0x20)
 30 |     |             executionBatch.offset := add(s, 0x20)
 31 |     |             executionBatch.length := calldataload(s)
 32 |     |             if or(shr(64, u), gt(add(s, shl(5, executionBatch.length)), e)) {
 33 |     |                 mstore(0x00, 0xba597e7e) // `DecodingError()`.
 34 |     |                 revert(0x1c, 0x04)
 35 |     |             }
 36 |     |             if executionBatch.length {
 37 |     |                 // Perform bounds checks on the decoded `executionBatch`.
 38 |     |                 // Loop runs out-of-gas if `executionBatch.length` is big enough to cause overflows.
 39 |     |                 for { let i := executionBatch.length } 1 { } {
 40 |     |                     i := sub(i, 1)
 41 |     |                     let p := calldataload(add(executionBatch.offset, shl(5, i)))
 42 |     |                     let c := add(executionBatch.offset, p)
 43 |     |                     let q := calldataload(add(c, 0x40))
 44 |     |                     let o := add(c, q)
 45 |     |                     // forgefmt: disable-next-item
 46 |     |                     if or(shr(64, or(calldataload(o), or(p, q))),
 47 |     |                         or(gt(add(c, 0x40), e), gt(add(o, calldataload(o)), e))) {
 48 |     |                         mstore(0x00, 0xba597e7e) // `DecodingError()`.
 49 |     |                         revert(0x1c, 0x04)
 50 |     |                     }
 51 |     |                     if iszero(i) { break }
 52 |     |                 }
 53 |     |             }
 54 |     |         }
 55 |     |     }
 56 |     | 
 57 |     |     function encodeBatch(Execution[] memory executions)
 58 |     |         internal
 59 |     |         pure
 60 |     |         returns (bytes memory callData)
 61 |     |     {
 62 |     |         callData = abi.encode(executions);
 63 |     |     }
 64 |     | 
 65 |     |     function decodeSingle(bytes calldata executionCalldata)
 66 |     |         internal
 67 |     |         pure
 68 |     |         returns (address target, uint256 value, bytes calldata callData)
 69 |     |     {
 70 |     |         target = address(bytes20(executionCalldata[0:20]));
 71 |     |         value = uint256(bytes32(executionCalldata[20:52]));
 72 |     |         callData = executionCalldata[52:];
 73 |     |     }
 74 |     | 
 75 |     |     function encodeSingle(
 76 |     |         address target,
 77 |     |         uint256 value,
 78 |     |         bytes memory callData
 79 |     |     )
 80 |     |         internal
 81 |     |         pure
 82 |     |         returns (bytes memory userOpCalldata)
 83 |     |     {
 84 |     |         userOpCalldata = abi.encodePacked(target, value, callData);
 85 |     |     }
 86 |     | }
 87 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/access/AccessControl.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | import {IAccessControl} from "./IAccessControl.sol";
   7 |     | import {Context} from "../utils/Context.sol";
   8 |     | import {IERC165, ERC165} from "../utils/introspection/ERC165.sol";
   9 |     | 
  10 |     | /**
  11 |     |  * @dev Contract module that allows children to implement role-based access
  12 |     |  * control mechanisms. This is a lightweight version that doesn't allow enumerating role
  13 |     |  * members except through off-chain means by accessing the contract event logs. Some
  14 |     |  * applications may benefit from on-chain enumerability, for those cases see
  15 |     |  * {AccessControlEnumerable}.
  16 |     |  *
  17 |     |  * Roles are referred to by their `bytes32` identifier. These should be exposed
  18 |     |  * in the external API and be unique. The best way to achieve this is by
  19 |     |  * using `public constant` hash digests:
  20 |     |  *
  21 |     |  * ```solidity
  22 |     |  * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
  23 |     |  * ```
  24 |     |  *
  25 |     |  * Roles can be used to represent a set of permissions. To restrict access to a
  26 |     |  * function call, use {hasRole}:
  27 |     |  *
  28 |     |  * ```solidity
  29 |     |  * function foo() public {
  30 |     |  *     require(hasRole(MY_ROLE, msg.sender));
  31 |     |  *     ...
  32 |     |  * }
  33 |     |  * ```
  34 |     |  *
  35 |     |  * Roles can be granted and revoked dynamically via the {grantRole} and
  36 |     |  * {revokeRole} functions. Each role has an associated admin role, and only
  37 |     |  * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
  38 |     |  *
  39 |     |  * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
  40 |     |  * that only accounts with this role will be able to grant or revoke other
  41 |     |  * roles. More complex role relationships can be created by using
  42 |     |  * {_setRoleAdmin}.
  43 |     |  *
  44 |     |  * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
  45 |     |  * grant and revoke this role. Extra precautions should be taken to secure
  46 |     |  * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
  47 |     |  * to enforce additional security measures for this role.
  48 |     |  */
  49 |     | abstract contract AccessControl is Context, IAccessControl, ERC165 {
  50 |     |     struct RoleData {
  51 |     |         mapping(address account => bool) hasRole;
  52 |     |         bytes32 adminRole;
  53 |     |     }
  54 |     | 
  55 |     |     mapping(bytes32 role => RoleData) private _roles;
  56 |     | 
  57 | *   |     bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
  58 |     | 
  59 |     |     /**
  60 |     |      * @dev Modifier that checks that an account has a specific role. Reverts
  61 |     |      * with an {AccessControlUnauthorizedAccount} error including the required role.
  62 |     |      */
  63 |     |     modifier onlyRole(bytes32 role) {
  64 | *   |         _checkRole(role);
  65 |     |         _;
  66 |     |     }
  67 |     | 
  68 |     |     /// @inheritdoc IERC165
  69 | *   |     function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
  70 | *   |         return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
  71 |     |     }
  72 |     | 
  73 |     |     /**
  74 |     |      * @dev Returns `true` if `account` has been granted `role`.
  75 |     |      */
  76 | *   |     function hasRole(bytes32 role, address account) public view virtual returns (bool) {
  77 | *   |         return _roles[role].hasRole[account];
  78 |     |     }
  79 |     | 
  80 |     |     /**
  81 |     |      * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
  82 |     |      * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
  83 |     |      */
  84 | *   |     function _checkRole(bytes32 role) internal view virtual {
  85 | *   |         _checkRole(role, _msgSender());
  86 |     |     }
  87 |     | 
  88 |     |     /**
  89 |     |      * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
  90 |     |      * is missing `role`.
  91 |     |      */
  92 | *   |     function _checkRole(bytes32 role, address account) internal view virtual {
  93 | *   |         if (!hasRole(role, account)) {
  94 |     |             revert AccessControlUnauthorizedAccount(account, role);
  95 |     |         }
  96 |     |     }
  97 |     | 
  98 |     |     /**
  99 |     |      * @dev Returns the admin role that controls `role`. See {grantRole} and
 100 |     |      * {revokeRole}.
 101 |     |      *
 102 |     |      * To change a role's admin, use {_setRoleAdmin}.
 103 |     |      */
 104 |     |     function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
 105 | *   |         return _roles[role].adminRole;
 106 |     |     }
 107 |     | 
 108 |     |     /**
 109 |     |      * @dev Grants `role` to `account`.
 110 |     |      *
 111 |     |      * If `account` had not been already granted `role`, emits a {RoleGranted}
 112 |     |      * event.
 113 |     |      *
 114 |     |      * Requirements:
 115 |     |      *
 116 |     |      * - the caller must have ``role``'s admin role.
 117 |     |      *
 118 |     |      * May emit a {RoleGranted} event.
 119 |     |      */
 120 |     |     function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
 121 |     |         _grantRole(role, account);
 122 |     |     }
 123 |     | 
 124 |     |     /**
 125 |     |      * @dev Revokes `role` from `account`.
 126 |     |      *
 127 |     |      * If `account` had been granted `role`, emits a {RoleRevoked} event.
 128 |     |      *
 129 |     |      * Requirements:
 130 |     |      *
 131 |     |      * - the caller must have ``role``'s admin role.
 132 |     |      *
 133 |     |      * May emit a {RoleRevoked} event.
 134 |     |      */
 135 |     |     function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
 136 |     |         _revokeRole(role, account);
 137 |     |     }
 138 |     | 
 139 |     |     /**
 140 |     |      * @dev Revokes `role` from the calling account.
 141 |     |      *
 142 |     |      * Roles are often managed via {grantRole} and {revokeRole}: this function's
 143 |     |      * purpose is to provide a mechanism for accounts to lose their privileges
 144 |     |      * if they are compromised (such as when a trusted device is misplaced).
 145 |     |      *
 146 |     |      * If the calling account had been revoked `role`, emits a {RoleRevoked}
 147 |     |      * event.
 148 |     |      *
 149 |     |      * Requirements:
 150 |     |      *
 151 |     |      * - the caller must be `callerConfirmation`.
 152 |     |      *
 153 |     |      * May emit a {RoleRevoked} event.
 154 |     |      */
 155 |     |     function renounceRole(bytes32 role, address callerConfirmation) public virtual {
 156 |     |         if (callerConfirmation != _msgSender()) {
 157 |     |             revert AccessControlBadConfirmation();
 158 |     |         }
 159 |     | 
 160 |     |         _revokeRole(role, callerConfirmation);
 161 |     |     }
 162 |     | 
 163 |     |     /**
 164 |     |      * @dev Sets `adminRole` as ``role``'s admin role.
 165 |     |      *
 166 |     |      * Emits a {RoleAdminChanged} event.
 167 |     |      */
 168 | *   |     function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
 169 | *   |         bytes32 previousAdminRole = getRoleAdmin(role);
 170 | *   |         _roles[role].adminRole = adminRole;
 171 | *   |         emit RoleAdminChanged(role, previousAdminRole, adminRole);
 172 |     |     }
 173 |     | 
 174 |     |     /**
 175 |     |      * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
 176 |     |      *
 177 |     |      * Internal function without access restriction.
 178 |     |      *
 179 |     |      * May emit a {RoleGranted} event.
 180 |     |      */
 181 | *   |     function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
 182 | *   |         if (!hasRole(role, account)) {
 183 | *   |             _roles[role].hasRole[account] = true;
 184 | *   |             emit RoleGranted(role, account, _msgSender());
 185 | *   |             return true;
 186 |     |         } else {
 187 | *   |             return false;
 188 |     |         }
 189 |     |     }
 190 |     | 
 191 |     |     /**
 192 |     |      * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
 193 |     |      *
 194 |     |      * Internal function without access restriction.
 195 |     |      *
 196 |     |      * May emit a {RoleRevoked} event.
 197 |     |      */
 198 |     |     function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
 199 |     |         if (hasRole(role, account)) {
 200 |     |             _roles[role].hasRole[account] = false;
 201 |     |             emit RoleRevoked(role, account, _msgSender());
 202 |     |             return true;
 203 |     |         } else {
 204 |     |             return false;
 205 |     |         }
 206 |     |     }
 207 |     | }
 208 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/access/IAccessControl.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)
   3 |     | 
   4 |     | pragma solidity >=0.8.4;
   5 |     | 
   6 |     | /**
   7 |     |  * @dev External interface of AccessControl declared to support ERC-165 detection.
   8 |     |  */
   9 |     | interface IAccessControl {
  10 |     |     /**
  11 |     |      * @dev The `account` is missing a role.
  12 |     |      */
  13 |     |     error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
  14 |     | 
  15 |     |     /**
  16 |     |      * @dev The caller of a function is not the expected one.
  17 |     |      *
  18 |     |      * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
  19 |     |      */
  20 |     |     error AccessControlBadConfirmation();
  21 |     | 
  22 |     |     /**
  23 |     |      * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
  24 |     |      *
  25 |     |      * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
  26 |     |      * {RoleAdminChanged} not being emitted to signal this.
  27 |     |      */
  28 |     |     event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
  29 |     | 
  30 |     |     /**
  31 |     |      * @dev Emitted when `account` is granted `role`.
  32 |     |      *
  33 |     |      * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
  34 |     |      * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
  35 |     |      */
  36 |     |     event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
  37 |     | 
  38 |     |     /**
  39 |     |      * @dev Emitted when `account` is revoked `role`.
  40 |     |      *
  41 |     |      * `sender` is the account that originated the contract call:
  42 |     |      *   - if using `revokeRole`, it is the admin role bearer
  43 |     |      *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
  44 |     |      */
  45 |     |     event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
  46 |     | 
  47 |     |     /**
  48 |     |      * @dev Returns `true` if `account` has been granted `role`.
  49 |     |      */
  50 |     |     function hasRole(bytes32 role, address account) external view returns (bool);
  51 |     | 
  52 |     |     /**
  53 |     |      * @dev Returns the admin role that controls `role`. See {grantRole} and
  54 |     |      * {revokeRole}.
  55 |     |      *
  56 |     |      * To change a role's admin, use {AccessControl-_setRoleAdmin}.
  57 |     |      */
  58 |     |     function getRoleAdmin(bytes32 role) external view returns (bytes32);
  59 |     | 
  60 |     |     /**
  61 |     |      * @dev Grants `role` to `account`.
  62 |     |      *
  63 |     |      * If `account` had not been already granted `role`, emits a {RoleGranted}
  64 |     |      * event.
  65 |     |      *
  66 |     |      * Requirements:
  67 |     |      *
  68 |     |      * - the caller must have ``role``'s admin role.
  69 |     |      */
  70 |     |     function grantRole(bytes32 role, address account) external;
  71 |     | 
  72 |     |     /**
  73 |     |      * @dev Revokes `role` from `account`.
  74 |     |      *
  75 |     |      * If `account` had been granted `role`, emits a {RoleRevoked} event.
  76 |     |      *
  77 |     |      * Requirements:
  78 |     |      *
  79 |     |      * - the caller must have ``role``'s admin role.
  80 |     |      */
  81 |     |     function revokeRole(bytes32 role, address account) external;
  82 |     | 
  83 |     |     /**
  84 |     |      * @dev Revokes `role` from the calling account.
  85 |     |      *
  86 |     |      * Roles are often managed via {grantRole} and {revokeRole}: this function's
  87 |     |      * purpose is to provide a mechanism for accounts to lose their privileges
  88 |     |      * if they are compromised (such as when a trusted device is misplaced).
  89 |     |      *
  90 |     |      * If the calling account had been granted `role`, emits a {RoleRevoked}
  91 |     |      * event.
  92 |     |      *
  93 |     |      * Requirements:
  94 |     |      *
  95 |     |      * - the caller must be `callerConfirmation`.
  96 |     |      */
  97 |     |     function renounceRole(bytes32 role, address callerConfirmation) external;
  98 |     | }
  99 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
  3 |     | 
  4 |     | pragma solidity >=0.6.2;
  5 |     | 
  6 |     | import {IERC20} from "./IERC20.sol";
  7 |     | import {IERC165} from "./IERC165.sol";
  8 |     | 
  9 |     | /**
 10 |     |  * @title IERC1363
 11 |     |  * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 12 |     |  *
 13 |     |  * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 14 |     |  * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 15 |     |  */
 16 |     | interface IERC1363 is IERC20, IERC165 {
 17 |     |     /*
 18 |     |      * Note: the ERC-165 identifier for this interface is 0xb0202a11.
 19 |     |      * 0xb0202a11 ===
 20 |     |      *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
 21 |     |      *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
 22 |     |      *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
 23 |     |      *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
 24 |     |      *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
 25 |     |      *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
 26 |     |      */
 27 |     | 
 28 |     |     /**
 29 |     |      * @dev Moves a `value` amount of tokens from the caller's account to `to`
 30 |     |      * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
 31 |     |      * @param to The address which you want to transfer to.
 32 |     |      * @param value The amount of tokens to be transferred.
 33 |     |      * @return A boolean value indicating whether the operation succeeded unless throwing.
 34 |     |      */
 35 |     |     function transferAndCall(address to, uint256 value) external returns (bool);
 36 |     | 
 37 |     |     /**
 38 |     |      * @dev Moves a `value` amount of tokens from the caller's account to `to`
 39 |     |      * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
 40 |     |      * @param to The address which you want to transfer to.
 41 |     |      * @param value The amount of tokens to be transferred.
 42 |     |      * @param data Additional data with no specified format, sent in call to `to`.
 43 |     |      * @return A boolean value indicating whether the operation succeeded unless throwing.
 44 |     |      */
 45 |     |     function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
 46 |     | 
 47 |     |     /**
 48 |     |      * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
 49 |     |      * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
 50 |     |      * @param from The address which you want to send tokens from.
 51 |     |      * @param to The address which you want to transfer to.
 52 |     |      * @param value The amount of tokens to be transferred.
 53 |     |      * @return A boolean value indicating whether the operation succeeded unless throwing.
 54 |     |      */
 55 |     |     function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
 56 |     | 
 57 |     |     /**
 58 |     |      * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
 59 |     |      * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
 60 |     |      * @param from The address which you want to send tokens from.
 61 |     |      * @param to The address which you want to transfer to.
 62 |     |      * @param value The amount of tokens to be transferred.
 63 |     |      * @param data Additional data with no specified format, sent in call to `to`.
 64 |     |      * @return A boolean value indicating whether the operation succeeded unless throwing.
 65 |     |      */
 66 |     |     function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
 67 |     | 
 68 |     |     /**
 69 |     |      * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
 70 |     |      * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
 71 |     |      * @param spender The address which will spend the funds.
 72 |     |      * @param value The amount of tokens to be spent.
 73 |     |      * @return A boolean value indicating whether the operation succeeded unless throwing.
 74 |     |      */
 75 |     |     function approveAndCall(address spender, uint256 value) external returns (bool);
 76 |     | 
 77 |     |     /**
 78 |     |      * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
 79 |     |      * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
 80 |     |      * @param spender The address which will spend the funds.
 81 |     |      * @param value The amount of tokens to be spent.
 82 |     |      * @param data Additional data with no specified format, sent in call to `spender`.
 83 |     |      * @return A boolean value indicating whether the operation succeeded unless throwing.
 84 |     |      */
 85 |     |     function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
 86 |     | }
 87 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol
 1 |     | // SPDX-License-Identifier: MIT
 2 |     | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
 3 |     | 
 4 |     | pragma solidity >=0.4.16;
 5 |     | 
 6 |     | import {IERC165} from "../utils/introspection/IERC165.sol";
 7 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol
 1 |     | // SPDX-License-Identifier: MIT
 2 |     | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
 3 |     | 
 4 |     | pragma solidity >=0.4.16;
 5 |     | 
 6 |     | import {IERC20} from "../token/ERC20/IERC20.sol";
 7 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/interfaces/IERC20Metadata.sol
 1 |     | // SPDX-License-Identifier: MIT
 2 |     | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20Metadata.sol)
 3 |     | 
 4 |     | pragma solidity >=0.6.2;
 5 |     | 
 6 |     | import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
 7 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)
   3 |     | 
   4 |     | pragma solidity >=0.6.2;
   5 |     | 
   6 |     | import {IERC20} from "../token/ERC20/IERC20.sol";
   7 |     | import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
   8 |     | 
   9 |     | /**
  10 |     |  * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
  11 |     |  * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
  12 |     |  */
  13 |     | interface IERC4626 is IERC20, IERC20Metadata {
  14 |     |     event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
  15 |     | 
  16 |     |     event Withdraw(
  17 |     |         address indexed sender,
  18 |     |         address indexed receiver,
  19 |     |         address indexed owner,
  20 |     |         uint256 assets,
  21 |     |         uint256 shares
  22 |     |     );
  23 |     | 
  24 |     |     /**
  25 |     |      * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
  26 |     |      *
  27 |     |      * - MUST be an ERC-20 token contract.
  28 |     |      * - MUST NOT revert.
  29 |     |      */
  30 |     |     function asset() external view returns (address assetTokenAddress);
  31 |     | 
  32 |     |     /**
  33 |     |      * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
  34 |     |      *
  35 |     |      * - SHOULD include any compounding that occurs from yield.
  36 |     |      * - MUST be inclusive of any fees that are charged against assets in the Vault.
  37 |     |      * - MUST NOT revert.
  38 |     |      */
  39 |     |     function totalAssets() external view returns (uint256 totalManagedAssets);
  40 |     | 
  41 |     |     /**
  42 |     |      * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
  43 |     |      * scenario where all the conditions are met.
  44 |     |      *
  45 |     |      * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
  46 |     |      * - MUST NOT show any variations depending on the caller.
  47 |     |      * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
  48 |     |      * - MUST NOT revert.
  49 |     |      *
  50 |     |      * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
  51 |     |      * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
  52 |     |      * from.
  53 |     |      */
  54 |     |     function convertToShares(uint256 assets) external view returns (uint256 shares);
  55 |     | 
  56 |     |     /**
  57 |     |      * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
  58 |     |      * scenario where all the conditions are met.
  59 |     |      *
  60 |     |      * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
  61 |     |      * - MUST NOT show any variations depending on the caller.
  62 |     |      * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
  63 |     |      * - MUST NOT revert.
  64 |     |      *
  65 |     |      * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
  66 |     |      * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
  67 |     |      * from.
  68 |     |      */
  69 |     |     function convertToAssets(uint256 shares) external view returns (uint256 assets);
  70 |     | 
  71 |     |     /**
  72 |     |      * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
  73 |     |      * through a deposit call.
  74 |     |      *
  75 |     |      * - MUST return a limited value if receiver is subject to some deposit limit.
  76 |     |      * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
  77 |     |      * - MUST NOT revert.
  78 |     |      */
  79 |     |     function maxDeposit(address receiver) external view returns (uint256 maxAssets);
  80 |     | 
  81 |     |     /**
  82 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
  83 |     |      * current on-chain conditions.
  84 |     |      *
  85 |     |      * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
  86 |     |      *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
  87 |     |      *   in the same transaction.
  88 |     |      * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
  89 |     |      *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
  90 |     |      * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
  91 |     |      * - MUST NOT revert.
  92 |     |      *
  93 |     |      * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
  94 |     |      * share price or some other type of condition, meaning the depositor will lose assets by depositing.
  95 |     |      */
  96 |     |     function previewDeposit(uint256 assets) external view returns (uint256 shares);
  97 |     | 
  98 |     |     /**
  99 |     |      * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
 100 |     |      *
 101 |     |      * - MUST emit the Deposit event.
 102 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
 103 |     |      *   deposit execution, and are accounted for during deposit.
 104 |     |      * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
 105 |     |      *   approving enough underlying tokens to the Vault contract, etc).
 106 |     |      *
 107 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
 108 |     |      */
 109 |     |     function deposit(uint256 assets, address receiver) external returns (uint256 shares);
 110 |     | 
 111 |     |     /**
 112 |     |      * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
 113 |     |      * - MUST return a limited value if receiver is subject to some mint limit.
 114 |     |      * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
 115 |     |      * - MUST NOT revert.
 116 |     |      */
 117 |     |     function maxMint(address receiver) external view returns (uint256 maxShares);
 118 |     | 
 119 |     |     /**
 120 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
 121 |     |      * current on-chain conditions.
 122 |     |      *
 123 |     |      * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
 124 |     |      *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
 125 |     |      *   same transaction.
 126 |     |      * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
 127 |     |      *   would be accepted, regardless if the user has enough tokens approved, etc.
 128 |     |      * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
 129 |     |      * - MUST NOT revert.
 130 |     |      *
 131 |     |      * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
 132 |     |      * share price or some other type of condition, meaning the depositor will lose assets by minting.
 133 |     |      */
 134 |     |     function previewMint(uint256 shares) external view returns (uint256 assets);
 135 |     | 
 136 |     |     /**
 137 |     |      * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
 138 |     |      *
 139 |     |      * - MUST emit the Deposit event.
 140 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
 141 |     |      *   execution, and are accounted for during mint.
 142 |     |      * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
 143 |     |      *   approving enough underlying tokens to the Vault contract, etc).
 144 |     |      *
 145 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
 146 |     |      */
 147 |     |     function mint(uint256 shares, address receiver) external returns (uint256 assets);
 148 |     | 
 149 |     |     /**
 150 |     |      * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
 151 |     |      * Vault, through a withdraw call.
 152 |     |      *
 153 |     |      * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
 154 |     |      * - MUST NOT revert.
 155 |     |      */
 156 |     |     function maxWithdraw(address owner) external view returns (uint256 maxAssets);
 157 |     | 
 158 |     |     /**
 159 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
 160 |     |      * given current on-chain conditions.
 161 |     |      *
 162 |     |      * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
 163 |     |      *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
 164 |     |      *   called
 165 |     |      *   in the same transaction.
 166 |     |      * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
 167 |     |      *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
 168 |     |      * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
 169 |     |      * - MUST NOT revert.
 170 |     |      *
 171 |     |      * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
 172 |     |      * share price or some other type of condition, meaning the depositor will lose assets by depositing.
 173 |     |      */
 174 |     |     function previewWithdraw(uint256 assets) external view returns (uint256 shares);
 175 |     | 
 176 |     |     /**
 177 |     |      * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
 178 |     |      *
 179 |     |      * - MUST emit the Withdraw event.
 180 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
 181 |     |      *   withdraw execution, and are accounted for during withdraw.
 182 |     |      * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
 183 |     |      *   not having enough shares, etc).
 184 |     |      *
 185 |     |      * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
 186 |     |      * Those methods should be performed separately.
 187 |     |      */
 188 |     |     function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
 189 |     | 
 190 |     |     /**
 191 |     |      * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
 192 |     |      * through a redeem call.
 193 |     |      *
 194 |     |      * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
 195 |     |      * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
 196 |     |      * - MUST NOT revert.
 197 |     |      */
 198 |     |     function maxRedeem(address owner) external view returns (uint256 maxShares);
 199 |     | 
 200 |     |     /**
 201 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,
 202 |     |      * given current on-chain conditions.
 203 |     |      *
 204 |     |      * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
 205 |     |      *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
 206 |     |      *   same transaction.
 207 |     |      * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
 208 |     |      *   redemption would be accepted, regardless if the user has enough shares, etc.
 209 |     |      * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
 210 |     |      * - MUST NOT revert.
 211 |     |      *
 212 |     |      * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
 213 |     |      * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
 214 |     |      */
 215 |     |     function previewRedeem(uint256 shares) external view returns (uint256 assets);
 216 |     | 
 217 |     |     /**
 218 |     |      * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
 219 |     |      *
 220 |     |      * - MUST emit the Withdraw event.
 221 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
 222 |     |      *   redeem execution, and are accounted for during redeem.
 223 |     |      * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
 224 |     |      *   not having enough shares, etc).
 225 |     |      *
 226 |     |      * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
 227 |     |      * Those methods should be performed separately.
 228 |     |      */
 229 |     |     function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
 230 |     | }
 231 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)
  3 |     | 
  4 |     | pragma solidity >=0.4.16;
  5 |     | 
  6 |     | interface IERC5267 {
  7 |     |     /**
  8 |     |      * @dev MAY be emitted to signal that the domain could have changed.
  9 |     |      */
 10 |     |     event EIP712DomainChanged();
 11 |     | 
 12 |     |     /**
 13 |     |      * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
 14 |     |      * signature.
 15 |     |      */
 16 |     |     function eip712Domain()
 17 |     |         external
 18 |     |         view
 19 |     |         returns (
 20 |     |             bytes1 fields,
 21 |     |             string memory name,
 22 |     |             string memory version,
 23 |     |             uint256 chainId,
 24 |     |             address verifyingContract,
 25 |     |             bytes32 salt,
 26 |     |             uint256[] memory extensions
 27 |     |         );
 28 |     | }
 29 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
   3 |     | pragma solidity >=0.8.4;
   4 |     | 
   5 |     | /**
   6 |     |  * @dev Standard ERC-20 Errors
   7 |     |  * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
   8 |     |  */
   9 |     | interface IERC20Errors {
  10 |     |     /**
  11 |     |      * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
  12 |     |      * @param sender Address whose tokens are being transferred.
  13 |     |      * @param balance Current balance for the interacting account.
  14 |     |      * @param needed Minimum amount required to perform a transfer.
  15 |     |      */
  16 |     |     error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
  17 |     | 
  18 |     |     /**
  19 |     |      * @dev Indicates a failure with the token `sender`. Used in transfers.
  20 |     |      * @param sender Address whose tokens are being transferred.
  21 |     |      */
  22 |     |     error ERC20InvalidSender(address sender);
  23 |     | 
  24 |     |     /**
  25 |     |      * @dev Indicates a failure with the token `receiver`. Used in transfers.
  26 |     |      * @param receiver Address to which tokens are being transferred.
  27 |     |      */
  28 |     |     error ERC20InvalidReceiver(address receiver);
  29 |     | 
  30 |     |     /**
  31 |     |      * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
  32 |     |      * @param spender Address that may be allowed to operate on tokens without being their owner.
  33 |     |      * @param allowance Amount of tokens a `spender` is allowed to operate with.
  34 |     |      * @param needed Minimum amount required to perform a transfer.
  35 |     |      */
  36 |     |     error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
  37 |     | 
  38 |     |     /**
  39 |     |      * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
  40 |     |      * @param approver Address initiating an approval operation.
  41 |     |      */
  42 |     |     error ERC20InvalidApprover(address approver);
  43 |     | 
  44 |     |     /**
  45 |     |      * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
  46 |     |      * @param spender Address that may be allowed to operate on tokens without being their owner.
  47 |     |      */
  48 |     |     error ERC20InvalidSpender(address spender);
  49 |     | }
  50 |     | 
  51 |     | /**
  52 |     |  * @dev Standard ERC-721 Errors
  53 |     |  * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
  54 |     |  */
  55 |     | interface IERC721Errors {
  56 |     |     /**
  57 |     |      * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
  58 |     |      * Used in balance queries.
  59 |     |      * @param owner Address of the current owner of a token.
  60 |     |      */
  61 |     |     error ERC721InvalidOwner(address owner);
  62 |     | 
  63 |     |     /**
  64 |     |      * @dev Indicates a `tokenId` whose `owner` is the zero address.
  65 |     |      * @param tokenId Identifier number of a token.
  66 |     |      */
  67 |     |     error ERC721NonexistentToken(uint256 tokenId);
  68 |     | 
  69 |     |     /**
  70 |     |      * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
  71 |     |      * @param sender Address whose tokens are being transferred.
  72 |     |      * @param tokenId Identifier number of a token.
  73 |     |      * @param owner Address of the current owner of a token.
  74 |     |      */
  75 |     |     error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
  76 |     | 
  77 |     |     /**
  78 |     |      * @dev Indicates a failure with the token `sender`. Used in transfers.
  79 |     |      * @param sender Address whose tokens are being transferred.
  80 |     |      */
  81 |     |     error ERC721InvalidSender(address sender);
  82 |     | 
  83 |     |     /**
  84 |     |      * @dev Indicates a failure with the token `receiver`. Used in transfers.
  85 |     |      * @param receiver Address to which tokens are being transferred.
  86 |     |      */
  87 |     |     error ERC721InvalidReceiver(address receiver);
  88 |     | 
  89 |     |     /**
  90 |     |      * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
  91 |     |      * @param operator Address that may be allowed to operate on tokens without being their owner.
  92 |     |      * @param tokenId Identifier number of a token.
  93 |     |      */
  94 |     |     error ERC721InsufficientApproval(address operator, uint256 tokenId);
  95 |     | 
  96 |     |     /**
  97 |     |      * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
  98 |     |      * @param approver Address initiating an approval operation.
  99 |     |      */
 100 |     |     error ERC721InvalidApprover(address approver);
 101 |     | 
 102 |     |     /**
 103 |     |      * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
 104 |     |      * @param operator Address that may be allowed to operate on tokens without being their owner.
 105 |     |      */
 106 |     |     error ERC721InvalidOperator(address operator);
 107 |     | }
 108 |     | 
 109 |     | /**
 110 |     |  * @dev Standard ERC-1155 Errors
 111 |     |  * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 112 |     |  */
 113 |     | interface IERC1155Errors {
 114 |     |     /**
 115 |     |      * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
 116 |     |      * @param sender Address whose tokens are being transferred.
 117 |     |      * @param balance Current balance for the interacting account.
 118 |     |      * @param needed Minimum amount required to perform a transfer.
 119 |     |      * @param tokenId Identifier number of a token.
 120 |     |      */
 121 |     |     error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
 122 |     | 
 123 |     |     /**
 124 |     |      * @dev Indicates a failure with the token `sender`. Used in transfers.
 125 |     |      * @param sender Address whose tokens are being transferred.
 126 |     |      */
 127 |     |     error ERC1155InvalidSender(address sender);
 128 |     | 
 129 |     |     /**
 130 |     |      * @dev Indicates a failure with the token `receiver`. Used in transfers.
 131 |     |      * @param receiver Address to which tokens are being transferred.
 132 |     |      */
 133 |     |     error ERC1155InvalidReceiver(address receiver);
 134 |     | 
 135 |     |     /**
 136 |     |      * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
 137 |     |      * @param operator Address that may be allowed to operate on tokens without being their owner.
 138 |     |      * @param owner Address of the current owner of a token.
 139 |     |      */
 140 |     |     error ERC1155MissingApprovalForAll(address operator, address owner);
 141 |     | 
 142 |     |     /**
 143 |     |      * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
 144 |     |      * @param approver Address initiating an approval operation.
 145 |     |      */
 146 |     |     error ERC1155InvalidApprover(address approver);
 147 |     | 
 148 |     |     /**
 149 |     |      * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
 150 |     |      * @param operator Address that may be allowed to operate on tokens without being their owner.
 151 |     |      */
 152 |     |     error ERC1155InvalidOperator(address operator);
 153 |     | 
 154 |     |     /**
 155 |     |      * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
 156 |     |      * Used in batch transfers.
 157 |     |      * @param idsLength Length of the array of token identifiers
 158 |     |      * @param valuesLength Length of the array of token amounts
 159 |     |      */
 160 |     |     error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
 161 |     | }
 162 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/proxy/Clones.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (proxy/Clones.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | import {Create2} from "../utils/Create2.sol";
   7 |     | import {Errors} from "../utils/Errors.sol";
   8 |     | 
   9 |     | /**
  10 |     |  * @dev https://eips.ethereum.org/EIPS/eip-1167[ERC-1167] is a standard for
  11 |     |  * deploying minimal proxy contracts, also known as "clones".
  12 |     |  *
  13 |     |  * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
  14 |     |  * > a minimal bytecode implementation that delegates all calls to a known, fixed address.
  15 |     |  *
  16 |     |  * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
  17 |     |  * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
  18 |     |  * deterministic method.
  19 |     |  */
  20 |     | library Clones {
  21 |     |     error CloneArgumentsTooLong();
  22 |     | 
  23 |     |     /**
  24 |     |      * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`.
  25 |     |      *
  26 |     |      * This function uses the create opcode, which should never revert.
  27 |     |      */
  28 |     |     function clone(address implementation) internal returns (address instance) {
  29 |     |         return clone(implementation, 0);
  30 |     |     }
  31 |     | 
  32 |     |     /**
  33 |     |      * @dev Same as {xref-Clones-clone-address-}[clone], but with a `value` parameter to send native currency
  34 |     |      * to the new contract.
  35 |     |      *
  36 |     |      * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
  37 |     |      * to always have enough balance for new deployments. Consider exposing this function under a payable method.
  38 |     |      */
  39 |     |     function clone(address implementation, uint256 value) internal returns (address instance) {
  40 |     |         if (address(this).balance < value) {
  41 |     |             revert Errors.InsufficientBalance(address(this).balance, value);
  42 |     |         }
  43 |     |         assembly ("memory-safe") {
  44 |     |             // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
  45 |     |             // of the `implementation` address with the bytecode before the address.
  46 |     |             mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
  47 |     |             // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
  48 |     |             mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
  49 |     |             instance := create(value, 0x09, 0x37)
  50 |     |         }
  51 |     |         if (instance == address(0)) {
  52 |     |             revert Errors.FailedDeployment();
  53 |     |         }
  54 |     |     }
  55 |     | 
  56 |     |     /**
  57 |     |      * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`.
  58 |     |      *
  59 |     |      * This function uses the create2 opcode and a `salt` to deterministically deploy
  60 |     |      * the clone. Using the same `implementation` and `salt` multiple times will revert, since
  61 |     |      * the clones cannot be deployed twice at the same address.
  62 |     |      */
  63 | *   |     function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
  64 | *   |         return cloneDeterministic(implementation, salt, 0);
  65 |     |     }
  66 |     | 
  67 |     |     /**
  68 |     |      * @dev Same as {xref-Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with
  69 |     |      * a `value` parameter to send native currency to the new contract.
  70 |     |      *
  71 |     |      * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
  72 |     |      * to always have enough balance for new deployments. Consider exposing this function under a payable method.
  73 |     |      */
  74 | *   |     function cloneDeterministic(
  75 |     |         address implementation,
  76 |     |         bytes32 salt,
  77 |     |         uint256 value
  78 | *   |     ) internal returns (address instance) {
  79 | *   |         if (address(this).balance < value) {
  80 |     |             revert Errors.InsufficientBalance(address(this).balance, value);
  81 |     |         }
  82 |     |         assembly ("memory-safe") {
  83 |     |             // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
  84 |     |             // of the `implementation` address with the bytecode before the address.
  85 | *   |             mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
  86 |     |             // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
  87 | *   |             mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
  88 | *   |             instance := create2(value, 0x09, 0x37, salt)
  89 |     |         }
  90 | *   |         if (instance == address(0)) {
  91 |     |             revert Errors.FailedDeployment();
  92 |     |         }
  93 |     |     }
  94 |     | 
  95 |     |     /**
  96 |     |      * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
  97 |     |      */
  98 |     |     function predictDeterministicAddress(
  99 |     |         address implementation,
 100 |     |         bytes32 salt,
 101 |     |         address deployer
 102 |     |     ) internal pure returns (address predicted) {
 103 |     |         assembly ("memory-safe") {
 104 |     |             let ptr := mload(0x40)
 105 |     |             mstore(add(ptr, 0x38), deployer)
 106 |     |             mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
 107 |     |             mstore(add(ptr, 0x14), implementation)
 108 |     |             mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
 109 |     |             mstore(add(ptr, 0x58), salt)
 110 |     |             mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
 111 |     |             predicted := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff)
 112 |     |         }
 113 |     |     }
 114 |     | 
 115 |     |     /**
 116 |     |      * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
 117 |     |      */
 118 |     |     function predictDeterministicAddress(
 119 |     |         address implementation,
 120 |     |         bytes32 salt
 121 |     |     ) internal view returns (address predicted) {
 122 |     |         return predictDeterministicAddress(implementation, salt, address(this));
 123 |     |     }
 124 |     | 
 125 |     |     /**
 126 |     |      * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom
 127 |     |      * immutable arguments. These are provided through `args` and cannot be changed after deployment. To
 128 |     |      * access the arguments within the implementation, use {fetchCloneArgs}.
 129 |     |      *
 130 |     |      * This function uses the create opcode, which should never revert.
 131 |     |      */
 132 |     |     function cloneWithImmutableArgs(address implementation, bytes memory args) internal returns (address instance) {
 133 |     |         return cloneWithImmutableArgs(implementation, args, 0);
 134 |     |     }
 135 |     | 
 136 |     |     /**
 137 |     |      * @dev Same as {xref-Clones-cloneWithImmutableArgs-address-bytes-}[cloneWithImmutableArgs], but with a `value`
 138 |     |      * parameter to send native currency to the new contract.
 139 |     |      *
 140 |     |      * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
 141 |     |      * to always have enough balance for new deployments. Consider exposing this function under a payable method.
 142 |     |      */
 143 |     |     function cloneWithImmutableArgs(
 144 |     |         address implementation,
 145 |     |         bytes memory args,
 146 |     |         uint256 value
 147 |     |     ) internal returns (address instance) {
 148 |     |         if (address(this).balance < value) {
 149 |     |             revert Errors.InsufficientBalance(address(this).balance, value);
 150 |     |         }
 151 |     |         bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
 152 |     |         assembly ("memory-safe") {
 153 |     |             instance := create(value, add(bytecode, 0x20), mload(bytecode))
 154 |     |         }
 155 |     |         if (instance == address(0)) {
 156 |     |             revert Errors.FailedDeployment();
 157 |     |         }
 158 |     |     }
 159 |     | 
 160 |     |     /**
 161 |     |      * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom
 162 |     |      * immutable arguments. These are provided through `args` and cannot be changed after deployment. To
 163 |     |      * access the arguments within the implementation, use {fetchCloneArgs}.
 164 |     |      *
 165 |     |      * This function uses the create2 opcode and a `salt` to deterministically deploy the clone. Using the same
 166 |     |      * `implementation`, `args` and `salt` multiple times will revert, since the clones cannot be deployed twice
 167 |     |      * at the same address.
 168 |     |      */
 169 |     |     function cloneDeterministicWithImmutableArgs(
 170 |     |         address implementation,
 171 |     |         bytes memory args,
 172 |     |         bytes32 salt
 173 |     |     ) internal returns (address instance) {
 174 |     |         return cloneDeterministicWithImmutableArgs(implementation, args, salt, 0);
 175 |     |     }
 176 |     | 
 177 |     |     /**
 178 |     |      * @dev Same as {xref-Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-}[cloneDeterministicWithImmutableArgs],
 179 |     |      * but with a `value` parameter to send native currency to the new contract.
 180 |     |      *
 181 |     |      * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
 182 |     |      * to always have enough balance for new deployments. Consider exposing this function under a payable method.
 183 |     |      */
 184 |     |     function cloneDeterministicWithImmutableArgs(
 185 |     |         address implementation,
 186 |     |         bytes memory args,
 187 |     |         bytes32 salt,
 188 |     |         uint256 value
 189 |     |     ) internal returns (address instance) {
 190 |     |         bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
 191 |     |         return Create2.deploy(value, salt, bytecode);
 192 |     |     }
 193 |     | 
 194 |     |     /**
 195 |     |      * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.
 196 |     |      */
 197 |     |     function predictDeterministicAddressWithImmutableArgs(
 198 |     |         address implementation,
 199 |     |         bytes memory args,
 200 |     |         bytes32 salt,
 201 |     |         address deployer
 202 |     |     ) internal pure returns (address predicted) {
 203 |     |         bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
 204 |     |         return Create2.computeAddress(salt, keccak256(bytecode), deployer);
 205 |     |     }
 206 |     | 
 207 |     |     /**
 208 |     |      * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.
 209 |     |      */
 210 |     |     function predictDeterministicAddressWithImmutableArgs(
 211 |     |         address implementation,
 212 |     |         bytes memory args,
 213 |     |         bytes32 salt
 214 |     |     ) internal view returns (address predicted) {
 215 |     |         return predictDeterministicAddressWithImmutableArgs(implementation, args, salt, address(this));
 216 |     |     }
 217 |     | 
 218 |     |     /**
 219 |     |      * @dev Get the immutable args attached to a clone.
 220 |     |      *
 221 |     |      * - If `instance` is a clone that was deployed using `clone` or `cloneDeterministic`, this
 222 |     |      *   function will return an empty array.
 223 |     |      * - If `instance` is a clone that was deployed using `cloneWithImmutableArgs` or
 224 |     |      *   `cloneDeterministicWithImmutableArgs`, this function will return the args array used at
 225 |     |      *   creation.
 226 |     |      * - If `instance` is NOT a clone deployed using this library, the behavior is undefined. This
 227 |     |      *   function should only be used to check addresses that are known to be clones.
 228 |     |      */
 229 |     |     function fetchCloneArgs(address instance) internal view returns (bytes memory) {
 230 |     |         bytes memory result = new bytes(instance.code.length - 45); // revert if length is too short
 231 |     |         assembly ("memory-safe") {
 232 |     |             extcodecopy(instance, add(result, 32), 45, mload(result))
 233 |     |         }
 234 |     |         return result;
 235 |     |     }
 236 |     | 
 237 |     |     /**
 238 |     |      * @dev Helper that prepares the initcode of the proxy with immutable args.
 239 |     |      *
 240 |     |      * An assembly variant of this function requires copying the `args` array, which can be efficiently done using
 241 |     |      * `mcopy`. Unfortunately, that opcode is not available before cancun. A pure solidity implementation using
 242 |     |      * abi.encodePacked is more expensive but also more portable and easier to review.
 243 |     |      *
 244 |     |      * NOTE: https://eips.ethereum.org/EIPS/eip-170[EIP-170] limits the length of the contract code to 24576 bytes.
 245 |     |      * With the proxy code taking 45 bytes, that limits the length of the immutable args to 24531 bytes.
 246 |     |      */
 247 |     |     function _cloneCodeWithImmutableArgs(
 248 |     |         address implementation,
 249 |     |         bytes memory args
 250 |     |     ) private pure returns (bytes memory) {
 251 |     |         if (args.length > 24531) revert CloneArgumentsTooLong();
 252 |     |         return
 253 |     |             abi.encodePacked(
 254 |     |                 hex"61",
 255 |     |                 uint16(args.length + 45),
 256 |     |                 hex"3d81600a3d39f3363d3d373d3d3d363d73",
 257 |     |                 implementation,
 258 |     |                 hex"5af43d82803e903d91602b57fd5bf3",
 259 |     |                 args
 260 |     |             );
 261 |     |     }
 262 |     | }
 263 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
  3 |     | 
  4 |     | pragma solidity >=0.4.16;
  5 |     | 
  6 |     | /**
  7 |     |  * @dev Interface of the ERC-20 standard as defined in the ERC.
  8 |     |  */
  9 |     | interface IERC20 {
 10 |     |     /**
 11 |     |      * @dev Emitted when `value` tokens are moved from one account (`from`) to
 12 |     |      * another (`to`).
 13 |     |      *
 14 |     |      * Note that `value` may be zero.
 15 |     |      */
 16 |     |     event Transfer(address indexed from, address indexed to, uint256 value);
 17 |     | 
 18 |     |     /**
 19 |     |      * @dev Emitted when the allowance of a `spender` for an `owner` is set by
 20 |     |      * a call to {approve}. `value` is the new allowance.
 21 |     |      */
 22 |     |     event Approval(address indexed owner, address indexed spender, uint256 value);
 23 |     | 
 24 |     |     /**
 25 |     |      * @dev Returns the value of tokens in existence.
 26 |     |      */
 27 |     |     function totalSupply() external view returns (uint256);
 28 |     | 
 29 |     |     /**
 30 |     |      * @dev Returns the value of tokens owned by `account`.
 31 |     |      */
 32 |     |     function balanceOf(address account) external view returns (uint256);
 33 |     | 
 34 |     |     /**
 35 |     |      * @dev Moves a `value` amount of tokens from the caller's account to `to`.
 36 |     |      *
 37 |     |      * Returns a boolean value indicating whether the operation succeeded.
 38 |     |      *
 39 |     |      * Emits a {Transfer} event.
 40 |     |      */
 41 |     |     function transfer(address to, uint256 value) external returns (bool);
 42 |     | 
 43 |     |     /**
 44 |     |      * @dev Returns the remaining number of tokens that `spender` will be
 45 |     |      * allowed to spend on behalf of `owner` through {transferFrom}. This is
 46 |     |      * zero by default.
 47 |     |      *
 48 |     |      * This value changes when {approve} or {transferFrom} are called.
 49 |     |      */
 50 |     |     function allowance(address owner, address spender) external view returns (uint256);
 51 |     | 
 52 |     |     /**
 53 |     |      * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
 54 |     |      * caller's tokens.
 55 |     |      *
 56 |     |      * Returns a boolean value indicating whether the operation succeeded.
 57 |     |      *
 58 |     |      * IMPORTANT: Beware that changing an allowance with this method brings the risk
 59 |     |      * that someone may use both the old and the new allowance by unfortunate
 60 |     |      * transaction ordering. One possible solution to mitigate this race
 61 |     |      * condition is to first reduce the spender's allowance to 0 and set the
 62 |     |      * desired value afterwards:
 63 |     |      * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
 64 |     |      *
 65 |     |      * Emits an {Approval} event.
 66 |     |      */
 67 |     |     function approve(address spender, uint256 value) external returns (bool);
 68 |     | 
 69 |     |     /**
 70 |     |      * @dev Moves a `value` amount of tokens from `from` to `to` using the
 71 |     |      * allowance mechanism. `value` is then deducted from the caller's
 72 |     |      * allowance.
 73 |     |      *
 74 |     |      * Returns a boolean value indicating whether the operation succeeded.
 75 |     |      *
 76 |     |      * Emits a {Transfer} event.
 77 |     |      */
 78 |     |     function transferFrom(address from, address to, uint256 value) external returns (bool);
 79 |     | }
 80 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
  3 |     | 
  4 |     | pragma solidity >=0.6.2;
  5 |     | 
  6 |     | import {IERC20} from "../IERC20.sol";
  7 |     | 
  8 |     | /**
  9 |     |  * @dev Interface for the optional metadata functions from the ERC-20 standard.
 10 |     |  */
 11 |     | interface IERC20Metadata is IERC20 {
 12 |     |     /**
 13 |     |      * @dev Returns the name of the token.
 14 |     |      */
 15 |     |     function name() external view returns (string memory);
 16 |     | 
 17 |     |     /**
 18 |     |      * @dev Returns the symbol of the token.
 19 |     |      */
 20 |     |     function symbol() external view returns (string memory);
 21 |     | 
 22 |     |     /**
 23 |     |      * @dev Returns the decimals places of the token.
 24 |     |      */
 25 |     |     function decimals() external view returns (uint8);
 26 |     | }
 27 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | import {IERC20} from "../IERC20.sol";
   7 |     | import {IERC1363} from "../../../interfaces/IERC1363.sol";
   8 |     | 
   9 |     | /**
  10 |     |  * @title SafeERC20
  11 |     |  * @dev Wrappers around ERC-20 operations that throw on failure (when the token
  12 |     |  * contract returns false). Tokens that return no value (and instead revert or
  13 |     |  * throw on failure) are also supported, non-reverting calls are assumed to be
  14 |     |  * successful.
  15 |     |  * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
  16 |     |  * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
  17 |     |  */
  18 |     | library SafeERC20 {
  19 |     |     /**
  20 |     |      * @dev An operation with an ERC-20 token failed.
  21 |     |      */
  22 |     |     error SafeERC20FailedOperation(address token);
  23 |     | 
  24 |     |     /**
  25 |     |      * @dev Indicates a failed `decreaseAllowance` request.
  26 |     |      */
  27 |     |     error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
  28 |     | 
  29 |     |     /**
  30 |     |      * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
  31 |     |      * non-reverting calls are assumed to be successful.
  32 |     |      */
  33 | *   |     function safeTransfer(IERC20 token, address to, uint256 value) internal {
  34 | *   |         _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
  35 |     |     }
  36 |     | 
  37 |     |     /**
  38 |     |      * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
  39 |     |      * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
  40 |     |      */
  41 | *   |     function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
  42 | *   |         _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
  43 |     |     }
  44 |     | 
  45 |     |     /**
  46 |     |      * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
  47 |     |      */
  48 |     |     function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
  49 |     |         return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
  50 |     |     }
  51 |     | 
  52 |     |     /**
  53 |     |      * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
  54 |     |      */
  55 |     |     function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
  56 |     |         return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
  57 |     |     }
  58 |     | 
  59 |     |     /**
  60 |     |      * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
  61 |     |      * non-reverting calls are assumed to be successful.
  62 |     |      *
  63 |     |      * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
  64 |     |      * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
  65 |     |      * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
  66 |     |      * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
  67 |     |      */
  68 |     |     function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
  69 |     |         uint256 oldAllowance = token.allowance(address(this), spender);
  70 |     |         forceApprove(token, spender, oldAllowance + value);
  71 |     |     }
  72 |     | 
  73 |     |     /**
  74 |     |      * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
  75 |     |      * value, non-reverting calls are assumed to be successful.
  76 |     |      *
  77 |     |      * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
  78 |     |      * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
  79 |     |      * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
  80 |     |      * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
  81 |     |      */
  82 |     |     function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
  83 |     |         unchecked {
  84 |     |             uint256 currentAllowance = token.allowance(address(this), spender);
  85 |     |             if (currentAllowance < requestedDecrease) {
  86 |     |                 revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
  87 |     |             }
  88 |     |             forceApprove(token, spender, currentAllowance - requestedDecrease);
  89 |     |         }
  90 |     |     }
  91 |     | 
  92 |     |     /**
  93 |     |      * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
  94 |     |      * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
  95 |     |      * to be set to zero before setting it to a non-zero value, such as USDT.
  96 |     |      *
  97 |     |      * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
  98 |     |      * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
  99 |     |      * set here.
 100 |     |      */
 101 |     |     function forceApprove(IERC20 token, address spender, uint256 value) internal {
 102 |     |         bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
 103 |     | 
 104 |     |         if (!_callOptionalReturnBool(token, approvalCall)) {
 105 |     |             _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
 106 |     |             _callOptionalReturn(token, approvalCall);
 107 |     |         }
 108 |     |     }
 109 |     | 
 110 |     |     /**
 111 |     |      * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
 112 |     |      * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
 113 |     |      * targeting contracts.
 114 |     |      *
 115 |     |      * Reverts if the returned value is other than `true`.
 116 |     |      */
 117 |     |     function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
 118 |     |         if (to.code.length == 0) {
 119 |     |             safeTransfer(token, to, value);
 120 |     |         } else if (!token.transferAndCall(to, value, data)) {
 121 |     |             revert SafeERC20FailedOperation(address(token));
 122 |     |         }
 123 |     |     }
 124 |     | 
 125 |     |     /**
 126 |     |      * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
 127 |     |      * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
 128 |     |      * targeting contracts.
 129 |     |      *
 130 |     |      * Reverts if the returned value is other than `true`.
 131 |     |      */
 132 |     |     function transferFromAndCallRelaxed(
 133 |     |         IERC1363 token,
 134 |     |         address from,
 135 |     |         address to,
 136 |     |         uint256 value,
 137 |     |         bytes memory data
 138 |     |     ) internal {
 139 |     |         if (to.code.length == 0) {
 140 |     |             safeTransferFrom(token, from, to, value);
 141 |     |         } else if (!token.transferFromAndCall(from, to, value, data)) {
 142 |     |             revert SafeERC20FailedOperation(address(token));
 143 |     |         }
 144 |     |     }
 145 |     | 
 146 |     |     /**
 147 |     |      * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
 148 |     |      * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
 149 |     |      * targeting contracts.
 150 |     |      *
 151 |     |      * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
 152 |     |      * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
 153 |     |      * once without retrying, and relies on the returned value to be true.
 154 |     |      *
 155 |     |      * Reverts if the returned value is other than `true`.
 156 |     |      */
 157 |     |     function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
 158 |     |         if (to.code.length == 0) {
 159 |     |             forceApprove(token, to, value);
 160 |     |         } else if (!token.approveAndCall(to, value, data)) {
 161 |     |             revert SafeERC20FailedOperation(address(token));
 162 |     |         }
 163 |     |     }
 164 |     | 
 165 |     |     /**
 166 |     |      * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
 167 |     |      * on the return value: the return value is optional (but if data is returned, it must not be false).
 168 |     |      * @param token The token targeted by the call.
 169 |     |      * @param data The call data (encoded using abi.encode or one of its variants).
 170 |     |      *
 171 |     |      * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
 172 |     |      */
 173 | *   |     function _callOptionalReturn(IERC20 token, bytes memory data) private {
 174 | *   |         uint256 returnSize;
 175 | *   |         uint256 returnValue;
 176 |     |         assembly ("memory-safe") {
 177 | *   |             let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
 178 |     |             // bubble errors
 179 | *   |             if iszero(success) {
 180 | *   |                 let ptr := mload(0x40)
 181 | *   |                 returndatacopy(ptr, 0, returndatasize())
 182 | *   |                 revert(ptr, returndatasize())
 183 |     |             }
 184 | *   |             returnSize := returndatasize()
 185 | *   |             returnValue := mload(0)
 186 |     |         }
 187 |     | 
 188 | *   |         if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
 189 | *   |             revert SafeERC20FailedOperation(address(token));
 190 |     |         }
 191 |     |     }
 192 |     | 
 193 |     |     /**
 194 |     |      * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
 195 |     |      * on the return value: the return value is optional (but if data is returned, it must not be false).
 196 |     |      * @param token The token targeted by the call.
 197 |     |      * @param data The call data (encoded using abi.encode or one of its variants).
 198 |     |      *
 199 |     |      * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
 200 |     |      */
 201 |     |     function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
 202 |     |         bool success;
 203 |     |         uint256 returnSize;
 204 |     |         uint256 returnValue;
 205 |     |         assembly ("memory-safe") {
 206 |     |             success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
 207 |     |             returnSize := returndatasize()
 208 |     |             returnValue := mload(0)
 209 |     |         }
 210 |     |         return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
 211 |     |     }
 212 |     | }
 213 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/Arrays.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)
   3 |     | // This file was procedurally generated from scripts/generate/templates/Arrays.js.
   4 |     | 
   5 |     | pragma solidity ^0.8.20;
   6 |     | 
   7 |     | import {Comparators} from "./Comparators.sol";
   8 |     | import {SlotDerivation} from "./SlotDerivation.sol";
   9 |     | import {StorageSlot} from "./StorageSlot.sol";
  10 |     | import {Math} from "./math/Math.sol";
  11 |     | 
  12 |     | /**
  13 |     |  * @dev Collection of functions related to array types.
  14 |     |  */
  15 |     | library Arrays {
  16 |     |     using SlotDerivation for bytes32;
  17 |     |     using StorageSlot for bytes32;
  18 |     | 
  19 |     |     /**
  20 |     |      * @dev Sort an array of uint256 (in memory) following the provided comparator function.
  21 |     |      *
  22 |     |      * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
  23 |     |      * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
  24 |     |      *
  25 |     |      * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
  26 |     |      * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
  27 |     |      * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
  28 |     |      * consume more gas than is available in a block, leading to potential DoS.
  29 |     |      *
  30 |     |      * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
  31 |     |      */
  32 |     |     function sort(
  33 |     |         uint256[] memory array,
  34 |     |         function(uint256, uint256) pure returns (bool) comp
  35 |     |     ) internal pure returns (uint256[] memory) {
  36 |     |         _quickSort(_begin(array), _end(array), comp);
  37 |     |         return array;
  38 |     |     }
  39 |     | 
  40 |     |     /**
  41 |     |      * @dev Variant of {sort} that sorts an array of uint256 in increasing order.
  42 |     |      */
  43 |     |     function sort(uint256[] memory array) internal pure returns (uint256[] memory) {
  44 |     |         sort(array, Comparators.lt);
  45 |     |         return array;
  46 |     |     }
  47 |     | 
  48 |     |     /**
  49 |     |      * @dev Sort an array of address (in memory) following the provided comparator function.
  50 |     |      *
  51 |     |      * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
  52 |     |      * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
  53 |     |      *
  54 |     |      * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
  55 |     |      * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
  56 |     |      * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
  57 |     |      * consume more gas than is available in a block, leading to potential DoS.
  58 |     |      *
  59 |     |      * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
  60 |     |      */
  61 |     |     function sort(
  62 |     |         address[] memory array,
  63 |     |         function(address, address) pure returns (bool) comp
  64 |     |     ) internal pure returns (address[] memory) {
  65 |     |         sort(_castToUint256Array(array), _castToUint256Comp(comp));
  66 |     |         return array;
  67 |     |     }
  68 |     | 
  69 |     |     /**
  70 |     |      * @dev Variant of {sort} that sorts an array of address in increasing order.
  71 |     |      */
  72 |     |     function sort(address[] memory array) internal pure returns (address[] memory) {
  73 |     |         sort(_castToUint256Array(array), Comparators.lt);
  74 |     |         return array;
  75 |     |     }
  76 |     | 
  77 |     |     /**
  78 |     |      * @dev Sort an array of bytes32 (in memory) following the provided comparator function.
  79 |     |      *
  80 |     |      * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
  81 |     |      * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
  82 |     |      *
  83 |     |      * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
  84 |     |      * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
  85 |     |      * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
  86 |     |      * consume more gas than is available in a block, leading to potential DoS.
  87 |     |      *
  88 |     |      * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
  89 |     |      */
  90 |     |     function sort(
  91 |     |         bytes32[] memory array,
  92 |     |         function(bytes32, bytes32) pure returns (bool) comp
  93 |     |     ) internal pure returns (bytes32[] memory) {
  94 |     |         sort(_castToUint256Array(array), _castToUint256Comp(comp));
  95 |     |         return array;
  96 |     |     }
  97 |     | 
  98 |     |     /**
  99 |     |      * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.
 100 |     |      */
 101 |     |     function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {
 102 |     |         sort(_castToUint256Array(array), Comparators.lt);
 103 |     |         return array;
 104 |     |     }
 105 |     | 
 106 |     |     /**
 107 |     |      * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops
 108 |     |      * at end (exclusive). Sorting follows the `comp` comparator.
 109 |     |      *
 110 |     |      * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.
 111 |     |      *
 112 |     |      * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should
 113 |     |      * be used only if the limits are within a memory array.
 114 |     |      */
 115 |     |     function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {
 116 |     |         unchecked {
 117 |     |             if (end - begin < 0x40) return;
 118 |     | 
 119 |     |             // Use first element as pivot
 120 |     |             uint256 pivot = _mload(begin);
 121 |     |             // Position where the pivot should be at the end of the loop
 122 |     |             uint256 pos = begin;
 123 |     | 
 124 |     |             for (uint256 it = begin + 0x20; it < end; it += 0x20) {
 125 |     |                 if (comp(_mload(it), pivot)) {
 126 |     |                     // If the value stored at the iterator's position comes before the pivot, we increment the
 127 |     |                     // position of the pivot and move the value there.
 128 |     |                     pos += 0x20;
 129 |     |                     _swap(pos, it);
 130 |     |                 }
 131 |     |             }
 132 |     | 
 133 |     |             _swap(begin, pos); // Swap pivot into place
 134 |     |             _quickSort(begin, pos, comp); // Sort the left side of the pivot
 135 |     |             _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot
 136 |     |         }
 137 |     |     }
 138 |     | 
 139 |     |     /**
 140 |     |      * @dev Pointer to the memory location of the first element of `array`.
 141 |     |      */
 142 |     |     function _begin(uint256[] memory array) private pure returns (uint256 ptr) {
 143 |     |         assembly ("memory-safe") {
 144 |     |             ptr := add(array, 0x20)
 145 |     |         }
 146 |     |     }
 147 |     | 
 148 |     |     /**
 149 |     |      * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word
 150 |     |      * that comes just after the last element of the array.
 151 |     |      */
 152 |     |     function _end(uint256[] memory array) private pure returns (uint256 ptr) {
 153 |     |         unchecked {
 154 |     |             return _begin(array) + array.length * 0x20;
 155 |     |         }
 156 |     |     }
 157 |     | 
 158 |     |     /**
 159 |     |      * @dev Load memory word (as a uint256) at location `ptr`.
 160 |     |      */
 161 |     |     function _mload(uint256 ptr) private pure returns (uint256 value) {
 162 |     |         assembly {
 163 |     |             value := mload(ptr)
 164 |     |         }
 165 |     |     }
 166 |     | 
 167 |     |     /**
 168 |     |      * @dev Swaps the elements memory location `ptr1` and `ptr2`.
 169 |     |      */
 170 |     |     function _swap(uint256 ptr1, uint256 ptr2) private pure {
 171 |     |         assembly {
 172 |     |             let value1 := mload(ptr1)
 173 |     |             let value2 := mload(ptr2)
 174 |     |             mstore(ptr1, value2)
 175 |     |             mstore(ptr2, value1)
 176 |     |         }
 177 |     |     }
 178 |     | 
 179 |     |     /// @dev Helper: low level cast address memory array to uint256 memory array
 180 |     |     function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {
 181 |     |         assembly {
 182 |     |             output := input
 183 |     |         }
 184 |     |     }
 185 |     | 
 186 |     |     /// @dev Helper: low level cast bytes32 memory array to uint256 memory array
 187 |     |     function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {
 188 |     |         assembly {
 189 |     |             output := input
 190 |     |         }
 191 |     |     }
 192 |     | 
 193 |     |     /// @dev Helper: low level cast address comp function to uint256 comp function
 194 |     |     function _castToUint256Comp(
 195 |     |         function(address, address) pure returns (bool) input
 196 |     |     ) private pure returns (function(uint256, uint256) pure returns (bool) output) {
 197 |     |         assembly {
 198 |     |             output := input
 199 |     |         }
 200 |     |     }
 201 |     | 
 202 |     |     /// @dev Helper: low level cast bytes32 comp function to uint256 comp function
 203 |     |     function _castToUint256Comp(
 204 |     |         function(bytes32, bytes32) pure returns (bool) input
 205 |     |     ) private pure returns (function(uint256, uint256) pure returns (bool) output) {
 206 |     |         assembly {
 207 |     |             output := input
 208 |     |         }
 209 |     |     }
 210 |     | 
 211 |     |     /**
 212 |     |      * @dev Searches a sorted `array` and returns the first index that contains
 213 |     |      * a value greater or equal to `element`. If no such index exists (i.e. all
 214 |     |      * values in the array are strictly less than `element`), the array length is
 215 |     |      * returned. Time complexity O(log n).
 216 |     |      *
 217 |     |      * NOTE: The `array` is expected to be sorted in ascending order, and to
 218 |     |      * contain no repeated elements.
 219 |     |      *
 220 |     |      * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks
 221 |     |      * support for repeated elements in the array. The {lowerBound} function should
 222 |     |      * be used instead.
 223 |     |      */
 224 |     |     function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
 225 |     |         uint256 low = 0;
 226 |     |         uint256 high = array.length;
 227 |     | 
 228 |     |         if (high == 0) {
 229 |     |             return 0;
 230 |     |         }
 231 |     | 
 232 |     |         while (low < high) {
 233 |     |             uint256 mid = Math.average(low, high);
 234 |     | 
 235 |     |             // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
 236 |     |             // because Math.average rounds towards zero (it does integer division with truncation).
 237 |     |             if (unsafeAccess(array, mid).value > element) {
 238 |     |                 high = mid;
 239 |     |             } else {
 240 |     |                 low = mid + 1;
 241 |     |             }
 242 |     |         }
 243 |     | 
 244 |     |         // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
 245 |     |         if (low > 0 && unsafeAccess(array, low - 1).value == element) {
 246 |     |             return low - 1;
 247 |     |         } else {
 248 |     |             return low;
 249 |     |         }
 250 |     |     }
 251 |     | 
 252 |     |     /**
 253 |     |      * @dev Searches an `array` sorted in ascending order and returns the first
 254 |     |      * index that contains a value greater or equal than `element`. If no such index
 255 |     |      * exists (i.e. all values in the array are strictly less than `element`), the array
 256 |     |      * length is returned. Time complexity O(log n).
 257 |     |      *
 258 |     |      * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].
 259 |     |      */
 260 |     |     function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
 261 |     |         uint256 low = 0;
 262 |     |         uint256 high = array.length;
 263 |     | 
 264 |     |         if (high == 0) {
 265 |     |             return 0;
 266 |     |         }
 267 |     | 
 268 |     |         while (low < high) {
 269 |     |             uint256 mid = Math.average(low, high);
 270 |     | 
 271 |     |             // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
 272 |     |             // because Math.average rounds towards zero (it does integer division with truncation).
 273 |     |             if (unsafeAccess(array, mid).value < element) {
 274 |     |                 // this cannot overflow because mid < high
 275 |     |                 unchecked {
 276 |     |                     low = mid + 1;
 277 |     |                 }
 278 |     |             } else {
 279 |     |                 high = mid;
 280 |     |             }
 281 |     |         }
 282 |     | 
 283 |     |         return low;
 284 |     |     }
 285 |     | 
 286 |     |     /**
 287 |     |      * @dev Searches an `array` sorted in ascending order and returns the first
 288 |     |      * index that contains a value strictly greater than `element`. If no such index
 289 |     |      * exists (i.e. all values in the array are strictly less than `element`), the array
 290 |     |      * length is returned. Time complexity O(log n).
 291 |     |      *
 292 |     |      * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].
 293 |     |      */
 294 |     |     function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
 295 |     |         uint256 low = 0;
 296 |     |         uint256 high = array.length;
 297 |     | 
 298 |     |         if (high == 0) {
 299 |     |             return 0;
 300 |     |         }
 301 |     | 
 302 |     |         while (low < high) {
 303 |     |             uint256 mid = Math.average(low, high);
 304 |     | 
 305 |     |             // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
 306 |     |             // because Math.average rounds towards zero (it does integer division with truncation).
 307 |     |             if (unsafeAccess(array, mid).value > element) {
 308 |     |                 high = mid;
 309 |     |             } else {
 310 |     |                 // this cannot overflow because mid < high
 311 |     |                 unchecked {
 312 |     |                     low = mid + 1;
 313 |     |                 }
 314 |     |             }
 315 |     |         }
 316 |     | 
 317 |     |         return low;
 318 |     |     }
 319 |     | 
 320 |     |     /**
 321 |     |      * @dev Same as {lowerBound}, but with an array in memory.
 322 |     |      */
 323 |     |     function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
 324 |     |         uint256 low = 0;
 325 |     |         uint256 high = array.length;
 326 |     | 
 327 |     |         if (high == 0) {
 328 |     |             return 0;
 329 |     |         }
 330 |     | 
 331 |     |         while (low < high) {
 332 |     |             uint256 mid = Math.average(low, high);
 333 |     | 
 334 |     |             // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
 335 |     |             // because Math.average rounds towards zero (it does integer division with truncation).
 336 |     |             if (unsafeMemoryAccess(array, mid) < element) {
 337 |     |                 // this cannot overflow because mid < high
 338 |     |                 unchecked {
 339 |     |                     low = mid + 1;
 340 |     |                 }
 341 |     |             } else {
 342 |     |                 high = mid;
 343 |     |             }
 344 |     |         }
 345 |     | 
 346 |     |         return low;
 347 |     |     }
 348 |     | 
 349 |     |     /**
 350 |     |      * @dev Same as {upperBound}, but with an array in memory.
 351 |     |      */
 352 |     |     function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
 353 |     |         uint256 low = 0;
 354 |     |         uint256 high = array.length;
 355 |     | 
 356 |     |         if (high == 0) {
 357 |     |             return 0;
 358 |     |         }
 359 |     | 
 360 |     |         while (low < high) {
 361 |     |             uint256 mid = Math.average(low, high);
 362 |     | 
 363 |     |             // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
 364 |     |             // because Math.average rounds towards zero (it does integer division with truncation).
 365 |     |             if (unsafeMemoryAccess(array, mid) > element) {
 366 |     |                 high = mid;
 367 |     |             } else {
 368 |     |                 // this cannot overflow because mid < high
 369 |     |                 unchecked {
 370 |     |                     low = mid + 1;
 371 |     |                 }
 372 |     |             }
 373 |     |         }
 374 |     | 
 375 |     |         return low;
 376 |     |     }
 377 |     | 
 378 |     |     /**
 379 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 380 |     |      *
 381 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 382 |     |      */
 383 |     |     function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
 384 |     |         bytes32 slot;
 385 |     |         assembly ("memory-safe") {
 386 |     |             slot := arr.slot
 387 |     |         }
 388 |     |         return slot.deriveArray().offset(pos).getAddressSlot();
 389 |     |     }
 390 |     | 
 391 |     |     /**
 392 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 393 |     |      *
 394 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 395 |     |      */
 396 |     |     function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
 397 |     |         bytes32 slot;
 398 |     |         assembly ("memory-safe") {
 399 |     |             slot := arr.slot
 400 |     |         }
 401 |     |         return slot.deriveArray().offset(pos).getBytes32Slot();
 402 |     |     }
 403 |     | 
 404 |     |     /**
 405 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 406 |     |      *
 407 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 408 |     |      */
 409 |     |     function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
 410 |     |         bytes32 slot;
 411 |     |         assembly ("memory-safe") {
 412 |     |             slot := arr.slot
 413 |     |         }
 414 |     |         return slot.deriveArray().offset(pos).getUint256Slot();
 415 |     |     }
 416 |     | 
 417 |     |     /**
 418 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 419 |     |      *
 420 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 421 |     |      */
 422 |     |     function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) {
 423 |     |         bytes32 slot;
 424 |     |         assembly ("memory-safe") {
 425 |     |             slot := arr.slot
 426 |     |         }
 427 |     |         return slot.deriveArray().offset(pos).getBytesSlot();
 428 |     |     }
 429 |     | 
 430 |     |     /**
 431 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 432 |     |      *
 433 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 434 |     |      */
 435 |     |     function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) {
 436 |     |         bytes32 slot;
 437 |     |         assembly ("memory-safe") {
 438 |     |             slot := arr.slot
 439 |     |         }
 440 |     |         return slot.deriveArray().offset(pos).getStringSlot();
 441 |     |     }
 442 |     | 
 443 |     |     /**
 444 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 445 |     |      *
 446 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 447 |     |      */
 448 |     |     function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
 449 |     |         assembly {
 450 |     |             res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
 451 |     |         }
 452 |     |     }
 453 |     | 
 454 |     |     /**
 455 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 456 |     |      *
 457 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 458 |     |      */
 459 |     |     function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {
 460 |     |         assembly {
 461 |     |             res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
 462 |     |         }
 463 |     |     }
 464 |     | 
 465 |     |     /**
 466 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 467 |     |      *
 468 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 469 |     |      */
 470 |     |     function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
 471 |     |         assembly {
 472 |     |             res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
 473 |     |         }
 474 |     |     }
 475 |     | 
 476 |     |     /**
 477 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 478 |     |      *
 479 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 480 |     |      */
 481 |     |     function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) {
 482 |     |         assembly {
 483 |     |             res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
 484 |     |         }
 485 |     |     }
 486 |     | 
 487 |     |     /**
 488 |     |      * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
 489 |     |      *
 490 |     |      * WARNING: Only use if you are certain `pos` is lower than the array length.
 491 |     |      */
 492 |     |     function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) {
 493 |     |         assembly {
 494 |     |             res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
 495 |     |         }
 496 |     |     }
 497 |     | 
 498 |     |     /**
 499 |     |      * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
 500 |     |      *
 501 |     |      * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
 502 |     |      */
 503 |     |     function unsafeSetLength(address[] storage array, uint256 len) internal {
 504 |     |         assembly ("memory-safe") {
 505 |     |             sstore(array.slot, len)
 506 |     |         }
 507 |     |     }
 508 |     | 
 509 |     |     /**
 510 |     |      * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
 511 |     |      *
 512 |     |      * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
 513 |     |      */
 514 |     |     function unsafeSetLength(bytes32[] storage array, uint256 len) internal {
 515 |     |         assembly ("memory-safe") {
 516 |     |             sstore(array.slot, len)
 517 |     |         }
 518 |     |     }
 519 |     | 
 520 |     |     /**
 521 |     |      * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
 522 |     |      *
 523 |     |      * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
 524 |     |      */
 525 |     |     function unsafeSetLength(uint256[] storage array, uint256 len) internal {
 526 |     |         assembly ("memory-safe") {
 527 |     |             sstore(array.slot, len)
 528 |     |         }
 529 |     |     }
 530 |     | 
 531 |     |     /**
 532 |     |      * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
 533 |     |      *
 534 |     |      * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
 535 |     |      */
 536 |     |     function unsafeSetLength(bytes[] storage array, uint256 len) internal {
 537 |     |         assembly ("memory-safe") {
 538 |     |             sstore(array.slot, len)
 539 |     |         }
 540 |     |     }
 541 |     | 
 542 |     |     /**
 543 |     |      * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
 544 |     |      *
 545 |     |      * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
 546 |     |      */
 547 |     |     function unsafeSetLength(string[] storage array, uint256 len) internal {
 548 |     |         assembly ("memory-safe") {
 549 |     |             sstore(array.slot, len)
 550 |     |         }
 551 |     |     }
 552 |     | }
 553 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/Comparators.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | 
  6 |     | /**
  7 |     |  * @dev Provides a set of functions to compare values.
  8 |     |  *
  9 |     |  * _Available since v5.1._
 10 |     |  */
 11 |     | library Comparators {
 12 |     |     function lt(uint256 a, uint256 b) internal pure returns (bool) {
 13 |     |         return a < b;
 14 |     |     }
 15 |     | 
 16 |     |     function gt(uint256 a, uint256 b) internal pure returns (bool) {
 17 |     |         return a > b;
 18 |     |     }
 19 |     | }
 20 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/Context.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | 
  6 |     | /**
  7 |     |  * @dev Provides information about the current execution context, including the
  8 |     |  * sender of the transaction and its data. While these are generally available
  9 |     |  * via msg.sender and msg.data, they should not be accessed in such a direct
 10 |     |  * manner, since when dealing with meta-transactions the account sending and
 11 |     |  * paying for execution may not be the actual sender (as far as an application
 12 |     |  * is concerned).
 13 |     |  *
 14 |     |  * This contract is only required for intermediate, library-like contracts.
 15 |     |  */
 16 |     | abstract contract Context {
 17 | *   |     function _msgSender() internal view virtual returns (address) {
 18 | *   |         return msg.sender;
 19 |     |     }
 20 |     | 
 21 |     |     function _msgData() internal view virtual returns (bytes calldata) {
 22 |     |         return msg.data;
 23 |     |     }
 24 |     | 
 25 |     |     function _contextSuffixLength() internal view virtual returns (uint256) {
 26 |     |         return 0;
 27 |     |     }
 28 |     | }
 29 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/Create2.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | 
  6 |     | import {Errors} from "./Errors.sol";
  7 |     | 
  8 |     | /**
  9 |     |  * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
 10 |     |  * `CREATE2` can be used to compute in advance the address where a smart
 11 |     |  * contract will be deployed, which allows for interesting new mechanisms known
 12 |     |  * as 'counterfactual interactions'.
 13 |     |  *
 14 |     |  * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
 15 |     |  * information.
 16 |     |  */
 17 |     | library Create2 {
 18 |     |     /**
 19 |     |      * @dev There's no code to deploy.
 20 |     |      */
 21 |     |     error Create2EmptyBytecode();
 22 |     | 
 23 |     |     /**
 24 |     |      * @dev Deploys a contract using `CREATE2`. The address where the contract
 25 |     |      * will be deployed can be known in advance via {computeAddress}.
 26 |     |      *
 27 |     |      * The bytecode for a contract can be obtained from Solidity with
 28 |     |      * `type(contractName).creationCode`.
 29 |     |      *
 30 |     |      * Requirements:
 31 |     |      *
 32 |     |      * - `bytecode` must not be empty.
 33 |     |      * - `salt` must have not been used for `bytecode` already.
 34 |     |      * - the factory must have a balance of at least `amount`.
 35 |     |      * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
 36 |     |      */
 37 |     |     function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {
 38 |     |         if (address(this).balance < amount) {
 39 |     |             revert Errors.InsufficientBalance(address(this).balance, amount);
 40 |     |         }
 41 |     |         if (bytecode.length == 0) {
 42 |     |             revert Create2EmptyBytecode();
 43 |     |         }
 44 |     |         assembly ("memory-safe") {
 45 |     |             addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
 46 |     |             // if no address was created, and returndata is not empty, bubble revert
 47 |     |             if and(iszero(addr), not(iszero(returndatasize()))) {
 48 |     |                 let p := mload(0x40)
 49 |     |                 returndatacopy(p, 0, returndatasize())
 50 |     |                 revert(p, returndatasize())
 51 |     |             }
 52 |     |         }
 53 |     |         if (addr == address(0)) {
 54 |     |             revert Errors.FailedDeployment();
 55 |     |         }
 56 |     |     }
 57 |     | 
 58 |     |     /**
 59 |     |      * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
 60 |     |      * `bytecodeHash` or `salt` will result in a new destination address.
 61 |     |      */
 62 |     |     function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
 63 |     |         return computeAddress(salt, bytecodeHash, address(this));
 64 |     |     }
 65 |     | 
 66 |     |     /**
 67 |     |      * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
 68 |     |      * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
 69 |     |      */
 70 |     |     function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {
 71 |     |         assembly ("memory-safe") {
 72 |     |             let ptr := mload(0x40) // Get free memory pointer
 73 |     | 
 74 |     |             // |                   | ↓ ptr ...  ↓ ptr + 0x0B (start) ...  ↓ ptr + 0x20 ...  ↓ ptr + 0x40 ...   |
 75 |     |             // |-------------------|---------------------------------------------------------------------------|
 76 |     |             // | bytecodeHash      |                                                        CCCCCCCCCCCCC...CC |
 77 |     |             // | salt              |                                      BBBBBBBBBBBBB...BB                   |
 78 |     |             // | deployer          | 000000...0000AAAAAAAAAAAAAAAAAAA...AA                                     |
 79 |     |             // | 0xFF              |            FF                                                             |
 80 |     |             // |-------------------|---------------------------------------------------------------------------|
 81 |     |             // | memory            | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
 82 |     |             // | keccak(start, 85) |            ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
 83 |     | 
 84 |     |             mstore(add(ptr, 0x40), bytecodeHash)
 85 |     |             mstore(add(ptr, 0x20), salt)
 86 |     |             mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes
 87 |     |             let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff
 88 |     |             mstore8(start, 0xff)
 89 |     |             addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)
 90 |     |         }
 91 |     |     }
 92 |     | }
 93 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/Errors.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | 
  6 |     | /**
  7 |     |  * @dev Collection of common custom errors used in multiple contracts
  8 |     |  *
  9 |     |  * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 10 |     |  * It is recommended to avoid relying on the error API for critical functionality.
 11 |     |  *
 12 |     |  * _Available since v5.1._
 13 |     |  */
 14 |     | library Errors {
 15 |     |     /**
 16 |     |      * @dev The ETH balance of the account is not enough to perform the operation.
 17 |     |      */
 18 |     |     error InsufficientBalance(uint256 balance, uint256 needed);
 19 |     | 
 20 |     |     /**
 21 |     |      * @dev A call to an address target failed. The target may have reverted.
 22 |     |      */
 23 |     |     error FailedCall();
 24 |     | 
 25 |     |     /**
 26 |     |      * @dev The deployment failed.
 27 |     |      */
 28 |     |     error FailedDeployment();
 29 |     | 
 30 |     |     /**
 31 |     |      * @dev A necessary precompile is missing.
 32 |     |      */
 33 |     |     error MissingPrecompile(address);
 34 |     | }
 35 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/Panic.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | 
  6 |     | /**
  7 |     |  * @dev Helper library for emitting standardized panic codes.
  8 |     |  *
  9 |     |  * ```solidity
 10 |     |  * contract Example {
 11 |     |  *      using Panic for uint256;
 12 |     |  *
 13 |     |  *      // Use any of the declared internal constants
 14 |     |  *      function foo() { Panic.GENERIC.panic(); }
 15 |     |  *
 16 |     |  *      // Alternatively
 17 |     |  *      function foo() { Panic.panic(Panic.GENERIC); }
 18 |     |  * }
 19 |     |  * ```
 20 |     |  *
 21 |     |  * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
 22 |     |  *
 23 |     |  * _Available since v5.1._
 24 |     |  */
 25 |     | // slither-disable-next-line unused-state
 26 |     | library Panic {
 27 |     |     /// @dev generic / unspecified error
 28 |     |     uint256 internal constant GENERIC = 0x00;
 29 |     |     /// @dev used by the assert() builtin
 30 |     |     uint256 internal constant ASSERT = 0x01;
 31 |     |     /// @dev arithmetic underflow or overflow
 32 | *   |     uint256 internal constant UNDER_OVERFLOW = 0x11;
 33 |     |     /// @dev division or modulo by zero
 34 |     |     uint256 internal constant DIVISION_BY_ZERO = 0x12;
 35 |     |     /// @dev enum conversion error
 36 |     |     uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
 37 |     |     /// @dev invalid encoding in storage
 38 |     |     uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
 39 |     |     /// @dev empty array pop
 40 |     |     uint256 internal constant EMPTY_ARRAY_POP = 0x31;
 41 |     |     /// @dev array out of bounds access
 42 |     |     uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
 43 |     |     /// @dev resource error (too large allocation or too large array)
 44 |     |     uint256 internal constant RESOURCE_ERROR = 0x41;
 45 |     |     /// @dev calling invalid internal function
 46 |     |     uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
 47 |     | 
 48 |     |     /// @dev Reverts with a panic code. Recommended to use with
 49 |     |     /// the internal constants with predefined codes.
 50 | *   |     function panic(uint256 code) internal pure {
 51 |     |         assembly ("memory-safe") {
 52 | *   |             mstore(0x00, 0x4e487b71)
 53 | *   |             mstore(0x20, code)
 54 | *   |             revert(0x1c, 0x24)
 55 |     |         }
 56 |     |     }
 57 |     | }
 58 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)
   3 |     | // This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.
   4 |     | 
   5 |     | pragma solidity ^0.8.20;
   6 |     | 
   7 |     | /**
   8 |     |  * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots
   9 |     |  * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by
  10 |     |  * the solidity language / compiler.
  11 |     |  *
  12 |     |  * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].
  13 |     |  *
  14 |     |  * Example usage:
  15 |     |  * ```solidity
  16 |     |  * contract Example {
  17 |     |  *     // Add the library methods
  18 |     |  *     using StorageSlot for bytes32;
  19 |     |  *     using SlotDerivation for bytes32;
  20 |     |  *
  21 |     |  *     // Declare a namespace
  22 |     |  *     string private constant _NAMESPACE = "<namespace>"; // eg. OpenZeppelin.Slot
  23 |     |  *
  24 |     |  *     function setValueInNamespace(uint256 key, address newValue) internal {
  25 |     |  *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
  26 |     |  *     }
  27 |     |  *
  28 |     |  *     function getValueInNamespace(uint256 key) internal view returns (address) {
  29 |     |  *         return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;
  30 |     |  *     }
  31 |     |  * }
  32 |     |  * ```
  33 |     |  *
  34 |     |  * TIP: Consider using this library along with {StorageSlot}.
  35 |     |  *
  36 |     |  * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking
  37 |     |  * upgrade safety will ignore the slots accessed through this library.
  38 |     |  *
  39 |     |  * _Available since v5.1._
  40 |     |  */
  41 |     | library SlotDerivation {
  42 |     |     /**
  43 |     |      * @dev Derive an ERC-7201 slot from a string (namespace).
  44 |     |      */
  45 |     |     function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {
  46 |     |         assembly ("memory-safe") {
  47 |     |             mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))
  48 |     |             slot := and(keccak256(0x00, 0x20), not(0xff))
  49 |     |         }
  50 |     |     }
  51 |     | 
  52 |     |     /**
  53 |     |      * @dev Add an offset to a slot to get the n-th element of a structure or an array.
  54 |     |      */
  55 |     |     function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {
  56 |     |         unchecked {
  57 |     |             return bytes32(uint256(slot) + pos);
  58 |     |         }
  59 |     |     }
  60 |     | 
  61 |     |     /**
  62 |     |      * @dev Derive the location of the first element in an array from the slot where the length is stored.
  63 |     |      */
  64 |     |     function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {
  65 |     |         assembly ("memory-safe") {
  66 |     |             mstore(0x00, slot)
  67 |     |             result := keccak256(0x00, 0x20)
  68 |     |         }
  69 |     |     }
  70 |     | 
  71 |     |     /**
  72 |     |      * @dev Derive the location of a mapping element from the key.
  73 |     |      */
  74 |     |     function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {
  75 |     |         assembly ("memory-safe") {
  76 |     |             mstore(0x00, and(key, shr(96, not(0))))
  77 |     |             mstore(0x20, slot)
  78 |     |             result := keccak256(0x00, 0x40)
  79 |     |         }
  80 |     |     }
  81 |     | 
  82 |     |     /**
  83 |     |      * @dev Derive the location of a mapping element from the key.
  84 |     |      */
  85 |     |     function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {
  86 |     |         assembly ("memory-safe") {
  87 |     |             mstore(0x00, iszero(iszero(key)))
  88 |     |             mstore(0x20, slot)
  89 |     |             result := keccak256(0x00, 0x40)
  90 |     |         }
  91 |     |     }
  92 |     | 
  93 |     |     /**
  94 |     |      * @dev Derive the location of a mapping element from the key.
  95 |     |      */
  96 |     |     function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {
  97 |     |         assembly ("memory-safe") {
  98 |     |             mstore(0x00, key)
  99 |     |             mstore(0x20, slot)
 100 |     |             result := keccak256(0x00, 0x40)
 101 |     |         }
 102 |     |     }
 103 |     | 
 104 |     |     /**
 105 |     |      * @dev Derive the location of a mapping element from the key.
 106 |     |      */
 107 |     |     function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {
 108 |     |         assembly ("memory-safe") {
 109 |     |             mstore(0x00, key)
 110 |     |             mstore(0x20, slot)
 111 |     |             result := keccak256(0x00, 0x40)
 112 |     |         }
 113 |     |     }
 114 |     | 
 115 |     |     /**
 116 |     |      * @dev Derive the location of a mapping element from the key.
 117 |     |      */
 118 |     |     function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {
 119 |     |         assembly ("memory-safe") {
 120 |     |             mstore(0x00, key)
 121 |     |             mstore(0x20, slot)
 122 |     |             result := keccak256(0x00, 0x40)
 123 |     |         }
 124 |     |     }
 125 |     | 
 126 |     |     /**
 127 |     |      * @dev Derive the location of a mapping element from the key.
 128 |     |      */
 129 |     |     function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {
 130 |     |         assembly ("memory-safe") {
 131 |     |             let length := mload(key)
 132 |     |             let begin := add(key, 0x20)
 133 |     |             let end := add(begin, length)
 134 |     |             let cache := mload(end)
 135 |     |             mstore(end, slot)
 136 |     |             result := keccak256(begin, add(length, 0x20))
 137 |     |             mstore(end, cache)
 138 |     |         }
 139 |     |     }
 140 |     | 
 141 |     |     /**
 142 |     |      * @dev Derive the location of a mapping element from the key.
 143 |     |      */
 144 |     |     function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {
 145 |     |         assembly ("memory-safe") {
 146 |     |             let length := mload(key)
 147 |     |             let begin := add(key, 0x20)
 148 |     |             let end := add(begin, length)
 149 |     |             let cache := mload(end)
 150 |     |             mstore(end, slot)
 151 |     |             result := keccak256(begin, add(length, 0x20))
 152 |     |             mstore(end, cache)
 153 |     |         }
 154 |     |     }
 155 |     | }
 156 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
   3 |     | // This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
   4 |     | 
   5 |     | pragma solidity ^0.8.20;
   6 |     | 
   7 |     | /**
   8 |     |  * @dev Library for reading and writing primitive types to specific storage slots.
   9 |     |  *
  10 |     |  * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
  11 |     |  * This library helps with reading and writing to such slots without the need for inline assembly.
  12 |     |  *
  13 |     |  * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
  14 |     |  *
  15 |     |  * Example usage to set ERC-1967 implementation slot:
  16 |     |  * ```solidity
  17 |     |  * contract ERC1967 {
  18 |     |  *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
  19 |     |  *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
  20 |     |  *
  21 |     |  *     function _getImplementation() internal view returns (address) {
  22 |     |  *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
  23 |     |  *     }
  24 |     |  *
  25 |     |  *     function _setImplementation(address newImplementation) internal {
  26 |     |  *         require(newImplementation.code.length > 0);
  27 |     |  *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
  28 |     |  *     }
  29 |     |  * }
  30 |     |  * ```
  31 |     |  *
  32 |     |  * TIP: Consider using this library along with {SlotDerivation}.
  33 |     |  */
  34 |     | library StorageSlot {
  35 |     |     struct AddressSlot {
  36 |     |         address value;
  37 |     |     }
  38 |     | 
  39 |     |     struct BooleanSlot {
  40 |     |         bool value;
  41 |     |     }
  42 |     | 
  43 |     |     struct Bytes32Slot {
  44 |     |         bytes32 value;
  45 |     |     }
  46 |     | 
  47 |     |     struct Uint256Slot {
  48 |     |         uint256 value;
  49 |     |     }
  50 |     | 
  51 |     |     struct Int256Slot {
  52 |     |         int256 value;
  53 |     |     }
  54 |     | 
  55 |     |     struct StringSlot {
  56 |     |         string value;
  57 |     |     }
  58 |     | 
  59 |     |     struct BytesSlot {
  60 |     |         bytes value;
  61 |     |     }
  62 |     | 
  63 |     |     /**
  64 |     |      * @dev Returns an `AddressSlot` with member `value` located at `slot`.
  65 |     |      */
  66 |     |     function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
  67 |     |         assembly ("memory-safe") {
  68 |     |             r.slot := slot
  69 |     |         }
  70 |     |     }
  71 |     | 
  72 |     |     /**
  73 |     |      * @dev Returns a `BooleanSlot` with member `value` located at `slot`.
  74 |     |      */
  75 |     |     function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
  76 |     |         assembly ("memory-safe") {
  77 |     |             r.slot := slot
  78 |     |         }
  79 |     |     }
  80 |     | 
  81 |     |     /**
  82 |     |      * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
  83 |     |      */
  84 |     |     function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
  85 |     |         assembly ("memory-safe") {
  86 |     |             r.slot := slot
  87 |     |         }
  88 |     |     }
  89 |     | 
  90 |     |     /**
  91 |     |      * @dev Returns a `Uint256Slot` with member `value` located at `slot`.
  92 |     |      */
  93 |     |     function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
  94 |     |         assembly ("memory-safe") {
  95 |     |             r.slot := slot
  96 |     |         }
  97 |     |     }
  98 |     | 
  99 |     |     /**
 100 |     |      * @dev Returns a `Int256Slot` with member `value` located at `slot`.
 101 |     |      */
 102 |     |     function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
 103 |     |         assembly ("memory-safe") {
 104 |     |             r.slot := slot
 105 |     |         }
 106 |     |     }
 107 |     | 
 108 |     |     /**
 109 |     |      * @dev Returns a `StringSlot` with member `value` located at `slot`.
 110 |     |      */
 111 |     |     function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
 112 |     |         assembly ("memory-safe") {
 113 |     |             r.slot := slot
 114 |     |         }
 115 |     |     }
 116 |     | 
 117 |     |     /**
 118 |     |      * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
 119 |     |      */
 120 |     |     function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
 121 |     |         assembly ("memory-safe") {
 122 |     |             r.slot := store.slot
 123 |     |         }
 124 |     |     }
 125 |     | 
 126 |     |     /**
 127 |     |      * @dev Returns a `BytesSlot` with member `value` located at `slot`.
 128 |     |      */
 129 |     |     function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
 130 |     |         assembly ("memory-safe") {
 131 |     |             r.slot := slot
 132 |     |         }
 133 |     |     }
 134 |     | 
 135 |     |     /**
 136 |     |      * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
 137 |     |      */
 138 |     |     function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
 139 |     |         assembly ("memory-safe") {
 140 |     |             r.slot := store.slot
 141 |     |         }
 142 |     |     }
 143 |     | }
 144 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/Strings.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | import {Math} from "./math/Math.sol";
   7 |     | import {SafeCast} from "./math/SafeCast.sol";
   8 |     | import {SignedMath} from "./math/SignedMath.sol";
   9 |     | 
  10 |     | /**
  11 |     |  * @dev String operations.
  12 |     |  */
  13 |     | library Strings {
  14 |     |     using SafeCast for *;
  15 |     | 
  16 |     |     bytes16 private constant HEX_DIGITS = "0123456789abcdef";
  17 |     |     uint8 private constant ADDRESS_LENGTH = 20;
  18 |     |     uint256 private constant SPECIAL_CHARS_LOOKUP =
  19 |     |         (1 << 0x08) | // backspace
  20 |     |             (1 << 0x09) | // tab
  21 |     |             (1 << 0x0a) | // newline
  22 |     |             (1 << 0x0c) | // form feed
  23 |     |             (1 << 0x0d) | // carriage return
  24 |     |             (1 << 0x22) | // double quote
  25 |     |             (1 << 0x5c); // backslash
  26 |     | 
  27 |     |     /**
  28 |     |      * @dev The `value` string doesn't fit in the specified `length`.
  29 |     |      */
  30 |     |     error StringsInsufficientHexLength(uint256 value, uint256 length);
  31 |     | 
  32 |     |     /**
  33 |     |      * @dev The string being parsed contains characters that are not in scope of the given base.
  34 |     |      */
  35 |     |     error StringsInvalidChar();
  36 |     | 
  37 |     |     /**
  38 |     |      * @dev The string being parsed is not a properly formatted address.
  39 |     |      */
  40 |     |     error StringsInvalidAddressFormat();
  41 |     | 
  42 |     |     /**
  43 |     |      * @dev Converts a `uint256` to its ASCII `string` decimal representation.
  44 |     |      */
  45 |     |     function toString(uint256 value) internal pure returns (string memory) {
  46 |     |         unchecked {
  47 |     |             uint256 length = Math.log10(value) + 1;
  48 |     |             string memory buffer = new string(length);
  49 |     |             uint256 ptr;
  50 |     |             assembly ("memory-safe") {
  51 |     |                 ptr := add(add(buffer, 0x20), length)
  52 |     |             }
  53 |     |             while (true) {
  54 |     |                 ptr--;
  55 |     |                 assembly ("memory-safe") {
  56 |     |                     mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
  57 |     |                 }
  58 |     |                 value /= 10;
  59 |     |                 if (value == 0) break;
  60 |     |             }
  61 |     |             return buffer;
  62 |     |         }
  63 |     |     }
  64 |     | 
  65 |     |     /**
  66 |     |      * @dev Converts a `int256` to its ASCII `string` decimal representation.
  67 |     |      */
  68 |     |     function toStringSigned(int256 value) internal pure returns (string memory) {
  69 |     |         return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
  70 |     |     }
  71 |     | 
  72 |     |     /**
  73 |     |      * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
  74 |     |      */
  75 |     |     function toHexString(uint256 value) internal pure returns (string memory) {
  76 |     |         unchecked {
  77 |     |             return toHexString(value, Math.log256(value) + 1);
  78 |     |         }
  79 |     |     }
  80 |     | 
  81 |     |     /**
  82 |     |      * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
  83 |     |      */
  84 |     |     function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
  85 |     |         uint256 localValue = value;
  86 |     |         bytes memory buffer = new bytes(2 * length + 2);
  87 |     |         buffer[0] = "0";
  88 |     |         buffer[1] = "x";
  89 |     |         for (uint256 i = 2 * length + 1; i > 1; --i) {
  90 |     |             buffer[i] = HEX_DIGITS[localValue & 0xf];
  91 |     |             localValue >>= 4;
  92 |     |         }
  93 |     |         if (localValue != 0) {
  94 |     |             revert StringsInsufficientHexLength(value, length);
  95 |     |         }
  96 |     |         return string(buffer);
  97 |     |     }
  98 |     | 
  99 |     |     /**
 100 |     |      * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
 101 |     |      * representation.
 102 |     |      */
 103 |     |     function toHexString(address addr) internal pure returns (string memory) {
 104 |     |         return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
 105 |     |     }
 106 |     | 
 107 |     |     /**
 108 |     |      * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal
 109 |     |      * representation, according to EIP-55.
 110 |     |      */
 111 |     |     function toChecksumHexString(address addr) internal pure returns (string memory) {
 112 |     |         bytes memory buffer = bytes(toHexString(addr));
 113 |     | 
 114 |     |         // hash the hex part of buffer (skip length + 2 bytes, length 40)
 115 |     |         uint256 hashValue;
 116 |     |         assembly ("memory-safe") {
 117 |     |             hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
 118 |     |         }
 119 |     | 
 120 |     |         for (uint256 i = 41; i > 1; --i) {
 121 |     |             // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)
 122 |     |             if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {
 123 |     |                 // case shift by xoring with 0x20
 124 |     |                 buffer[i] ^= 0x20;
 125 |     |             }
 126 |     |             hashValue >>= 4;
 127 |     |         }
 128 |     |         return string(buffer);
 129 |     |     }
 130 |     | 
 131 |     |     /**
 132 |     |      * @dev Converts a `bytes` buffer to its ASCII `string` hexadecimal representation.
 133 |     |      */
 134 |     |     function toHexString(bytes memory input) internal pure returns (string memory) {
 135 |     |         unchecked {
 136 |     |             bytes memory buffer = new bytes(2 * input.length + 2);
 137 |     |             buffer[0] = "0";
 138 |     |             buffer[1] = "x";
 139 |     |             for (uint256 i = 0; i < input.length; ++i) {
 140 |     |                 uint8 v = uint8(input[i]);
 141 |     |                 buffer[2 * i + 2] = HEX_DIGITS[v >> 4];
 142 |     |                 buffer[2 * i + 3] = HEX_DIGITS[v & 0xf];
 143 |     |             }
 144 |     |             return string(buffer);
 145 |     |         }
 146 |     |     }
 147 |     | 
 148 |     |     /**
 149 |     |      * @dev Returns true if the two strings are equal.
 150 |     |      */
 151 |     |     function equal(string memory a, string memory b) internal pure returns (bool) {
 152 |     |         return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
 153 |     |     }
 154 |     | 
 155 |     |     /**
 156 |     |      * @dev Parse a decimal string and returns the value as a `uint256`.
 157 |     |      *
 158 |     |      * Requirements:
 159 |     |      * - The string must be formatted as `[0-9]*`
 160 |     |      * - The result must fit into an `uint256` type
 161 |     |      */
 162 |     |     function parseUint(string memory input) internal pure returns (uint256) {
 163 |     |         return parseUint(input, 0, bytes(input).length);
 164 |     |     }
 165 |     | 
 166 |     |     /**
 167 |     |      * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and
 168 |     |      * `end` (excluded).
 169 |     |      *
 170 |     |      * Requirements:
 171 |     |      * - The substring must be formatted as `[0-9]*`
 172 |     |      * - The result must fit into an `uint256` type
 173 |     |      */
 174 |     |     function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
 175 |     |         (bool success, uint256 value) = tryParseUint(input, begin, end);
 176 |     |         if (!success) revert StringsInvalidChar();
 177 |     |         return value;
 178 |     |     }
 179 |     | 
 180 |     |     /**
 181 |     |      * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.
 182 |     |      *
 183 |     |      * NOTE: This function will revert if the result does not fit in a `uint256`.
 184 |     |      */
 185 |     |     function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {
 186 |     |         return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);
 187 |     |     }
 188 |     | 
 189 |     |     /**
 190 |     |      * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid
 191 |     |      * character.
 192 |     |      *
 193 |     |      * NOTE: This function will revert if the result does not fit in a `uint256`.
 194 |     |      */
 195 |     |     function tryParseUint(
 196 |     |         string memory input,
 197 |     |         uint256 begin,
 198 |     |         uint256 end
 199 |     |     ) internal pure returns (bool success, uint256 value) {
 200 |     |         if (end > bytes(input).length || begin > end) return (false, 0);
 201 |     |         return _tryParseUintUncheckedBounds(input, begin, end);
 202 |     |     }
 203 |     | 
 204 |     |     /**
 205 |     |      * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
 206 |     |      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
 207 |     |      */
 208 |     |     function _tryParseUintUncheckedBounds(
 209 |     |         string memory input,
 210 |     |         uint256 begin,
 211 |     |         uint256 end
 212 |     |     ) private pure returns (bool success, uint256 value) {
 213 |     |         bytes memory buffer = bytes(input);
 214 |     | 
 215 |     |         uint256 result = 0;
 216 |     |         for (uint256 i = begin; i < end; ++i) {
 217 |     |             uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
 218 |     |             if (chr > 9) return (false, 0);
 219 |     |             result *= 10;
 220 |     |             result += chr;
 221 |     |         }
 222 |     |         return (true, result);
 223 |     |     }
 224 |     | 
 225 |     |     /**
 226 |     |      * @dev Parse a decimal string and returns the value as a `int256`.
 227 |     |      *
 228 |     |      * Requirements:
 229 |     |      * - The string must be formatted as `[-+]?[0-9]*`
 230 |     |      * - The result must fit in an `int256` type.
 231 |     |      */
 232 |     |     function parseInt(string memory input) internal pure returns (int256) {
 233 |     |         return parseInt(input, 0, bytes(input).length);
 234 |     |     }
 235 |     | 
 236 |     |     /**
 237 |     |      * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and
 238 |     |      * `end` (excluded).
 239 |     |      *
 240 |     |      * Requirements:
 241 |     |      * - The substring must be formatted as `[-+]?[0-9]*`
 242 |     |      * - The result must fit in an `int256` type.
 243 |     |      */
 244 |     |     function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {
 245 |     |         (bool success, int256 value) = tryParseInt(input, begin, end);
 246 |     |         if (!success) revert StringsInvalidChar();
 247 |     |         return value;
 248 |     |     }
 249 |     | 
 250 |     |     /**
 251 |     |      * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if
 252 |     |      * the result does not fit in a `int256`.
 253 |     |      *
 254 |     |      * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
 255 |     |      */
 256 |     |     function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {
 257 |     |         return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);
 258 |     |     }
 259 |     | 
 260 |     |     uint256 private constant ABS_MIN_INT256 = 2 ** 255;
 261 |     | 
 262 |     |     /**
 263 |     |      * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid
 264 |     |      * character or if the result does not fit in a `int256`.
 265 |     |      *
 266 |     |      * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.
 267 |     |      */
 268 |     |     function tryParseInt(
 269 |     |         string memory input,
 270 |     |         uint256 begin,
 271 |     |         uint256 end
 272 |     |     ) internal pure returns (bool success, int256 value) {
 273 |     |         if (end > bytes(input).length || begin > end) return (false, 0);
 274 |     |         return _tryParseIntUncheckedBounds(input, begin, end);
 275 |     |     }
 276 |     | 
 277 |     |     /**
 278 |     |      * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that
 279 |     |      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
 280 |     |      */
 281 |     |     function _tryParseIntUncheckedBounds(
 282 |     |         string memory input,
 283 |     |         uint256 begin,
 284 |     |         uint256 end
 285 |     |     ) private pure returns (bool success, int256 value) {
 286 |     |         bytes memory buffer = bytes(input);
 287 |     | 
 288 |     |         // Check presence of a negative sign.
 289 |     |         bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
 290 |     |         bool positiveSign = sign == bytes1("+");
 291 |     |         bool negativeSign = sign == bytes1("-");
 292 |     |         uint256 offset = (positiveSign || negativeSign).toUint();
 293 |     | 
 294 |     |         (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);
 295 |     | 
 296 |     |         if (absSuccess && absValue < ABS_MIN_INT256) {
 297 |     |             return (true, negativeSign ? -int256(absValue) : int256(absValue));
 298 |     |         } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {
 299 |     |             return (true, type(int256).min);
 300 |     |         } else return (false, 0);
 301 |     |     }
 302 |     | 
 303 |     |     /**
 304 |     |      * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`.
 305 |     |      *
 306 |     |      * Requirements:
 307 |     |      * - The string must be formatted as `(0x)?[0-9a-fA-F]*`
 308 |     |      * - The result must fit in an `uint256` type.
 309 |     |      */
 310 |     |     function parseHexUint(string memory input) internal pure returns (uint256) {
 311 |     |         return parseHexUint(input, 0, bytes(input).length);
 312 |     |     }
 313 |     | 
 314 |     |     /**
 315 |     |      * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and
 316 |     |      * `end` (excluded).
 317 |     |      *
 318 |     |      * Requirements:
 319 |     |      * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`
 320 |     |      * - The result must fit in an `uint256` type.
 321 |     |      */
 322 |     |     function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {
 323 |     |         (bool success, uint256 value) = tryParseHexUint(input, begin, end);
 324 |     |         if (!success) revert StringsInvalidChar();
 325 |     |         return value;
 326 |     |     }
 327 |     | 
 328 |     |     /**
 329 |     |      * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.
 330 |     |      *
 331 |     |      * NOTE: This function will revert if the result does not fit in a `uint256`.
 332 |     |      */
 333 |     |     function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {
 334 |     |         return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);
 335 |     |     }
 336 |     | 
 337 |     |     /**
 338 |     |      * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an
 339 |     |      * invalid character.
 340 |     |      *
 341 |     |      * NOTE: This function will revert if the result does not fit in a `uint256`.
 342 |     |      */
 343 |     |     function tryParseHexUint(
 344 |     |         string memory input,
 345 |     |         uint256 begin,
 346 |     |         uint256 end
 347 |     |     ) internal pure returns (bool success, uint256 value) {
 348 |     |         if (end > bytes(input).length || begin > end) return (false, 0);
 349 |     |         return _tryParseHexUintUncheckedBounds(input, begin, end);
 350 |     |     }
 351 |     | 
 352 |     |     /**
 353 |     |      * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
 354 |     |      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
 355 |     |      */
 356 |     |     function _tryParseHexUintUncheckedBounds(
 357 |     |         string memory input,
 358 |     |         uint256 begin,
 359 |     |         uint256 end
 360 |     |     ) private pure returns (bool success, uint256 value) {
 361 |     |         bytes memory buffer = bytes(input);
 362 |     | 
 363 |     |         // skip 0x prefix if present
 364 |     |         bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
 365 |     |         uint256 offset = hasPrefix.toUint() * 2;
 366 |     | 
 367 |     |         uint256 result = 0;
 368 |     |         for (uint256 i = begin + offset; i < end; ++i) {
 369 |     |             uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));
 370 |     |             if (chr > 15) return (false, 0);
 371 |     |             result *= 16;
 372 |     |             unchecked {
 373 |     |                 // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
 374 |     |                 // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.
 375 |     |                 result += chr;
 376 |     |             }
 377 |     |         }
 378 |     |         return (true, result);
 379 |     |     }
 380 |     | 
 381 |     |     /**
 382 |     |      * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`.
 383 |     |      *
 384 |     |      * Requirements:
 385 |     |      * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`
 386 |     |      */
 387 |     |     function parseAddress(string memory input) internal pure returns (address) {
 388 |     |         return parseAddress(input, 0, bytes(input).length);
 389 |     |     }
 390 |     | 
 391 |     |     /**
 392 |     |      * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and
 393 |     |      * `end` (excluded).
 394 |     |      *
 395 |     |      * Requirements:
 396 |     |      * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`
 397 |     |      */
 398 |     |     function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {
 399 |     |         (bool success, address value) = tryParseAddress(input, begin, end);
 400 |     |         if (!success) revert StringsInvalidAddressFormat();
 401 |     |         return value;
 402 |     |     }
 403 |     | 
 404 |     |     /**
 405 |     |      * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
 406 |     |      * formatted address. See {parseAddress-string} requirements.
 407 |     |      */
 408 |     |     function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
 409 |     |         return tryParseAddress(input, 0, bytes(input).length);
 410 |     |     }
 411 |     | 
 412 |     |     /**
 413 |     |      * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
 414 |     |      * formatted address. See {parseAddress-string-uint256-uint256} requirements.
 415 |     |      */
 416 |     |     function tryParseAddress(
 417 |     |         string memory input,
 418 |     |         uint256 begin,
 419 |     |         uint256 end
 420 |     |     ) internal pure returns (bool success, address value) {
 421 |     |         if (end > bytes(input).length || begin > end) return (false, address(0));
 422 |     | 
 423 |     |         bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty
 424 |     |         uint256 expectedLength = 40 + hasPrefix.toUint() * 2;
 425 |     | 
 426 |     |         // check that input is the correct length
 427 |     |         if (end - begin == expectedLength) {
 428 |     |             // length guarantees that this does not overflow, and value is at most type(uint160).max
 429 |     |             (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);
 430 |     |             return (s, address(uint160(v)));
 431 |     |         } else {
 432 |     |             return (false, address(0));
 433 |     |         }
 434 |     |     }
 435 |     | 
 436 |     |     function _tryParseChr(bytes1 chr) private pure returns (uint8) {
 437 |     |         uint8 value = uint8(chr);
 438 |     | 
 439 |     |         // Try to parse `chr`:
 440 |     |         // - Case 1: [0-9]
 441 |     |         // - Case 2: [a-f]
 442 |     |         // - Case 3: [A-F]
 443 |     |         // - otherwise not supported
 444 |     |         unchecked {
 445 |     |             if (value > 47 && value < 58) value -= 48;
 446 |     |             else if (value > 96 && value < 103) value -= 87;
 447 |     |             else if (value > 64 && value < 71) value -= 55;
 448 |     |             else return type(uint8).max;
 449 |     |         }
 450 |     | 
 451 |     |         return value;
 452 |     |     }
 453 |     | 
 454 |     |     /**
 455 |     |      * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
 456 |     |      *
 457 |     |      * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
 458 |     |      *
 459 |     |      * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
 460 |     |      * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
 461 |     |      * characters that are not in this range, but other tooling may provide different results.
 462 |     |      */
 463 |     |     function escapeJSON(string memory input) internal pure returns (string memory) {
 464 |     |         bytes memory buffer = bytes(input);
 465 |     |         bytes memory output = new bytes(2 * buffer.length); // worst case scenario
 466 |     |         uint256 outputLength = 0;
 467 |     | 
 468 |     |         for (uint256 i; i < buffer.length; ++i) {
 469 |     |             bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
 470 |     |             if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
 471 |     |                 output[outputLength++] = "\\";
 472 |     |                 if (char == 0x08) output[outputLength++] = "b";
 473 |     |                 else if (char == 0x09) output[outputLength++] = "t";
 474 |     |                 else if (char == 0x0a) output[outputLength++] = "n";
 475 |     |                 else if (char == 0x0c) output[outputLength++] = "f";
 476 |     |                 else if (char == 0x0d) output[outputLength++] = "r";
 477 |     |                 else if (char == 0x5c) output[outputLength++] = "\\";
 478 |     |                 else if (char == 0x22) {
 479 |     |                     // solhint-disable-next-line quotes
 480 |     |                     output[outputLength++] = '"';
 481 |     |                 }
 482 |     |             } else {
 483 |     |                 output[outputLength++] = char;
 484 |     |             }
 485 |     |         }
 486 |     |         // write the actual length and deallocate unused memory
 487 |     |         assembly ("memory-safe") {
 488 |     |             mstore(output, outputLength)
 489 |     |             mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
 490 |     |         }
 491 |     | 
 492 |     |         return string(output);
 493 |     |     }
 494 |     | 
 495 |     |     /**
 496 |     |      * @dev Reads a bytes32 from a bytes array without bounds checking.
 497 |     |      *
 498 |     |      * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
 499 |     |      * assembly block as such would prevent some optimizations.
 500 |     |      */
 501 |     |     function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
 502 |     |         // This is not memory safe in the general case, but all calls to this private function are within bounds.
 503 |     |         assembly ("memory-safe") {
 504 |     |             value := mload(add(add(buffer, 0x20), offset))
 505 |     |         }
 506 |     |     }
 507 |     | }
 508 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | /**
   7 |     |  * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
   8 |     |  *
   9 |     |  * These functions can be used to verify that a message was signed by the holder
  10 |     |  * of the private keys of a given address.
  11 |     |  */
  12 |     | library ECDSA {
  13 |     |     enum RecoverError {
  14 |     |         NoError,
  15 |     |         InvalidSignature,
  16 |     |         InvalidSignatureLength,
  17 |     |         InvalidSignatureS
  18 |     |     }
  19 |     | 
  20 |     |     /**
  21 |     |      * @dev The signature derives the `address(0)`.
  22 |     |      */
  23 |     |     error ECDSAInvalidSignature();
  24 |     | 
  25 |     |     /**
  26 |     |      * @dev The signature has an invalid length.
  27 |     |      */
  28 |     |     error ECDSAInvalidSignatureLength(uint256 length);
  29 |     | 
  30 |     |     /**
  31 |     |      * @dev The signature has an S value that is in the upper half order.
  32 |     |      */
  33 |     |     error ECDSAInvalidSignatureS(bytes32 s);
  34 |     | 
  35 |     |     /**
  36 |     |      * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
  37 |     |      * return address(0) without also returning an error description. Errors are documented using an enum (error type)
  38 |     |      * and a bytes32 providing additional information about the error.
  39 |     |      *
  40 |     |      * If no error is returned, then the address can be used for verification purposes.
  41 |     |      *
  42 |     |      * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
  43 |     |      * this function rejects them by requiring the `s` value to be in the lower
  44 |     |      * half order, and the `v` value to be either 27 or 28.
  45 |     |      *
  46 |     |      * IMPORTANT: `hash` _must_ be the result of a hash operation for the
  47 |     |      * verification to be secure: it is possible to craft signatures that
  48 |     |      * recover to arbitrary addresses for non-hashed data. A safe way to ensure
  49 |     |      * this is by receiving a hash of the original message (which may otherwise
  50 |     |      * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
  51 |     |      *
  52 |     |      * Documentation for signature generation:
  53 |     |      * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
  54 |     |      * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
  55 |     |      */
  56 |     |     function tryRecover(
  57 |     |         bytes32 hash,
  58 |     |         bytes memory signature
  59 |     |     ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
  60 |     |         if (signature.length == 65) {
  61 |     |             bytes32 r;
  62 |     |             bytes32 s;
  63 |     |             uint8 v;
  64 |     |             // ecrecover takes the signature parameters, and the only way to get them
  65 |     |             // currently is to use assembly.
  66 |     |             assembly ("memory-safe") {
  67 |     |                 r := mload(add(signature, 0x20))
  68 |     |                 s := mload(add(signature, 0x40))
  69 |     |                 v := byte(0, mload(add(signature, 0x60)))
  70 |     |             }
  71 |     |             return tryRecover(hash, v, r, s);
  72 |     |         } else {
  73 |     |             return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
  74 |     |         }
  75 |     |     }
  76 |     | 
  77 |     |     /**
  78 |     |      * @dev Returns the address that signed a hashed message (`hash`) with
  79 |     |      * `signature`. This address can then be used for verification purposes.
  80 |     |      *
  81 |     |      * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
  82 |     |      * this function rejects them by requiring the `s` value to be in the lower
  83 |     |      * half order, and the `v` value to be either 27 or 28.
  84 |     |      *
  85 |     |      * IMPORTANT: `hash` _must_ be the result of a hash operation for the
  86 |     |      * verification to be secure: it is possible to craft signatures that
  87 |     |      * recover to arbitrary addresses for non-hashed data. A safe way to ensure
  88 |     |      * this is by receiving a hash of the original message (which may otherwise
  89 |     |      * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
  90 |     |      */
  91 |     |     function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
  92 |     |         (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
  93 |     |         _throwError(error, errorArg);
  94 |     |         return recovered;
  95 |     |     }
  96 |     | 
  97 |     |     /**
  98 |     |      * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
  99 |     |      *
 100 |     |      * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
 101 |     |      */
 102 |     |     function tryRecover(
 103 |     |         bytes32 hash,
 104 |     |         bytes32 r,
 105 |     |         bytes32 vs
 106 |     |     ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
 107 |     |         unchecked {
 108 |     |             bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
 109 |     |             // We do not check for an overflow here since the shift operation results in 0 or 1.
 110 |     |             uint8 v = uint8((uint256(vs) >> 255) + 27);
 111 |     |             return tryRecover(hash, v, r, s);
 112 |     |         }
 113 |     |     }
 114 |     | 
 115 |     |     /**
 116 |     |      * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
 117 |     |      */
 118 |     |     function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
 119 |     |         (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
 120 |     |         _throwError(error, errorArg);
 121 |     |         return recovered;
 122 |     |     }
 123 |     | 
 124 |     |     /**
 125 |     |      * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
 126 |     |      * `r` and `s` signature fields separately.
 127 |     |      */
 128 |     |     function tryRecover(
 129 |     |         bytes32 hash,
 130 |     |         uint8 v,
 131 |     |         bytes32 r,
 132 |     |         bytes32 s
 133 |     |     ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
 134 |     |         // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
 135 |     |         // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
 136 |     |         // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
 137 |     |         // signatures from current libraries generate a unique signature with an s-value in the lower half order.
 138 |     |         //
 139 |     |         // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
 140 |     |         // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
 141 |     |         // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
 142 |     |         // these malleable signatures as well.
 143 |     |         if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
 144 |     |             return (address(0), RecoverError.InvalidSignatureS, s);
 145 |     |         }
 146 |     | 
 147 |     |         // If the signature is valid (and not malleable), return the signer address
 148 |     |         address signer = ecrecover(hash, v, r, s);
 149 |     |         if (signer == address(0)) {
 150 |     |             return (address(0), RecoverError.InvalidSignature, bytes32(0));
 151 |     |         }
 152 |     | 
 153 |     |         return (signer, RecoverError.NoError, bytes32(0));
 154 |     |     }
 155 |     | 
 156 |     |     /**
 157 |     |      * @dev Overload of {ECDSA-recover} that receives the `v`,
 158 |     |      * `r` and `s` signature fields separately.
 159 |     |      */
 160 |     |     function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
 161 |     |         (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
 162 |     |         _throwError(error, errorArg);
 163 |     |         return recovered;
 164 |     |     }
 165 |     | 
 166 |     |     /**
 167 |     |      * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
 168 |     |      */
 169 |     |     function _throwError(RecoverError error, bytes32 errorArg) private pure {
 170 |     |         if (error == RecoverError.NoError) {
 171 |     |             return; // no error: do nothing
 172 |     |         } else if (error == RecoverError.InvalidSignature) {
 173 |     |             revert ECDSAInvalidSignature();
 174 |     |         } else if (error == RecoverError.InvalidSignatureLength) {
 175 |     |             revert ECDSAInvalidSignatureLength(uint256(errorArg));
 176 |     |         } else if (error == RecoverError.InvalidSignatureS) {
 177 |     |             revert ECDSAInvalidSignatureS(errorArg);
 178 |     |         }
 179 |     |     }
 180 |     | }
 181 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/cryptography/Hashes.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/Hashes.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | 
  6 |     | /**
  7 |     |  * @dev Library of standard hash functions.
  8 |     |  *
  9 |     |  * _Available since v5.1._
 10 |     |  */
 11 |     | library Hashes {
 12 |     |     /**
 13 |     |      * @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs.
 14 |     |      *
 15 |     |      * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 16 |     |      */
 17 |     |     function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) {
 18 |     |         return a < b ? efficientKeccak256(a, b) : efficientKeccak256(b, a);
 19 |     |     }
 20 |     | 
 21 |     |     /**
 22 |     |      * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
 23 |     |      */
 24 |     |     function efficientKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32 value) {
 25 |     |         assembly ("memory-safe") {
 26 |     |             mstore(0x00, a)
 27 |     |             mstore(0x20, b)
 28 |     |             value := keccak256(0x00, 0x40)
 29 |     |         }
 30 |     |     }
 31 |     | }
 32 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MerkleProof.sol)
   3 |     | // This file was procedurally generated from scripts/generate/templates/MerkleProof.js.
   4 |     | 
   5 |     | pragma solidity ^0.8.20;
   6 |     | 
   7 |     | import {Hashes} from "./Hashes.sol";
   8 |     | 
   9 |     | /**
  10 |     |  * @dev These functions deal with verification of Merkle Tree proofs.
  11 |     |  *
  12 |     |  * The tree and the proofs can be generated using our
  13 |     |  * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
  14 |     |  * You will find a quickstart guide in the readme.
  15 |     |  *
  16 |     |  * WARNING: You should avoid using leaf values that are 64 bytes long prior to
  17 |     |  * hashing, or use a hash function other than keccak256 for hashing leaves.
  18 |     |  * This is because the concatenation of a sorted pair of internal nodes in
  19 |     |  * the Merkle tree could be reinterpreted as a leaf value.
  20 |     |  * OpenZeppelin's JavaScript library generates Merkle trees that are safe
  21 |     |  * against this attack out of the box.
  22 |     |  *
  23 |     |  * IMPORTANT: Consider memory side-effects when using custom hashing functions
  24 |     |  * that access memory in an unsafe way.
  25 |     |  *
  26 |     |  * NOTE: This library supports proof verification for merkle trees built using
  27 |     |  * custom _commutative_ hashing functions (i.e. `H(a, b) == H(b, a)`). Proving
  28 |     |  * leaf inclusion in trees built using non-commutative hashing functions requires
  29 |     |  * additional logic that is not supported by this library.
  30 |     |  */
  31 |     | library MerkleProof {
  32 |     |     /**
  33 |     |      *@dev The multiproof provided is not valid.
  34 |     |      */
  35 |     |     error MerkleProofInvalidMultiproof();
  36 |     | 
  37 |     |     /**
  38 |     |      * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
  39 |     |      * defined by `root`. For this, a `proof` must be provided, containing
  40 |     |      * sibling hashes on the branch from the leaf to the root of the tree. Each
  41 |     |      * pair of leaves and each pair of pre-images are assumed to be sorted.
  42 |     |      *
  43 |     |      * This version handles proofs in memory with the default hashing function.
  44 |     |      */
  45 |     |     function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
  46 |     |         return processProof(proof, leaf) == root;
  47 |     |     }
  48 |     | 
  49 |     |     /**
  50 |     |      * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
  51 |     |      * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
  52 |     |      * hash matches the root of the tree. When processing the proof, the pairs
  53 |     |      * of leaves & pre-images are assumed to be sorted.
  54 |     |      *
  55 |     |      * This version handles proofs in memory with the default hashing function.
  56 |     |      */
  57 |     |     function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
  58 |     |         bytes32 computedHash = leaf;
  59 |     |         for (uint256 i = 0; i < proof.length; i++) {
  60 |     |             computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
  61 |     |         }
  62 |     |         return computedHash;
  63 |     |     }
  64 |     | 
  65 |     |     /**
  66 |     |      * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
  67 |     |      * defined by `root`. For this, a `proof` must be provided, containing
  68 |     |      * sibling hashes on the branch from the leaf to the root of the tree. Each
  69 |     |      * pair of leaves and each pair of pre-images are assumed to be sorted.
  70 |     |      *
  71 |     |      * This version handles proofs in memory with a custom hashing function.
  72 |     |      */
  73 |     |     function verify(
  74 |     |         bytes32[] memory proof,
  75 |     |         bytes32 root,
  76 |     |         bytes32 leaf,
  77 |     |         function(bytes32, bytes32) view returns (bytes32) hasher
  78 |     |     ) internal view returns (bool) {
  79 |     |         return processProof(proof, leaf, hasher) == root;
  80 |     |     }
  81 |     | 
  82 |     |     /**
  83 |     |      * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
  84 |     |      * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
  85 |     |      * hash matches the root of the tree. When processing the proof, the pairs
  86 |     |      * of leaves & pre-images are assumed to be sorted.
  87 |     |      *
  88 |     |      * This version handles proofs in memory with a custom hashing function.
  89 |     |      */
  90 |     |     function processProof(
  91 |     |         bytes32[] memory proof,
  92 |     |         bytes32 leaf,
  93 |     |         function(bytes32, bytes32) view returns (bytes32) hasher
  94 |     |     ) internal view returns (bytes32) {
  95 |     |         bytes32 computedHash = leaf;
  96 |     |         for (uint256 i = 0; i < proof.length; i++) {
  97 |     |             computedHash = hasher(computedHash, proof[i]);
  98 |     |         }
  99 |     |         return computedHash;
 100 |     |     }
 101 |     | 
 102 |     |     /**
 103 |     |      * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
 104 |     |      * defined by `root`. For this, a `proof` must be provided, containing
 105 |     |      * sibling hashes on the branch from the leaf to the root of the tree. Each
 106 |     |      * pair of leaves and each pair of pre-images are assumed to be sorted.
 107 |     |      *
 108 |     |      * This version handles proofs in calldata with the default hashing function.
 109 |     |      */
 110 |     |     function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
 111 |     |         return processProofCalldata(proof, leaf) == root;
 112 |     |     }
 113 |     | 
 114 |     |     /**
 115 |     |      * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
 116 |     |      * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
 117 |     |      * hash matches the root of the tree. When processing the proof, the pairs
 118 |     |      * of leaves & pre-images are assumed to be sorted.
 119 |     |      *
 120 |     |      * This version handles proofs in calldata with the default hashing function.
 121 |     |      */
 122 |     |     function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
 123 |     |         bytes32 computedHash = leaf;
 124 |     |         for (uint256 i = 0; i < proof.length; i++) {
 125 |     |             computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
 126 |     |         }
 127 |     |         return computedHash;
 128 |     |     }
 129 |     | 
 130 |     |     /**
 131 |     |      * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
 132 |     |      * defined by `root`. For this, a `proof` must be provided, containing
 133 |     |      * sibling hashes on the branch from the leaf to the root of the tree. Each
 134 |     |      * pair of leaves and each pair of pre-images are assumed to be sorted.
 135 |     |      *
 136 |     |      * This version handles proofs in calldata with a custom hashing function.
 137 |     |      */
 138 |     |     function verifyCalldata(
 139 |     |         bytes32[] calldata proof,
 140 |     |         bytes32 root,
 141 |     |         bytes32 leaf,
 142 |     |         function(bytes32, bytes32) view returns (bytes32) hasher
 143 |     |     ) internal view returns (bool) {
 144 |     |         return processProofCalldata(proof, leaf, hasher) == root;
 145 |     |     }
 146 |     | 
 147 |     |     /**
 148 |     |      * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
 149 |     |      * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
 150 |     |      * hash matches the root of the tree. When processing the proof, the pairs
 151 |     |      * of leaves & pre-images are assumed to be sorted.
 152 |     |      *
 153 |     |      * This version handles proofs in calldata with a custom hashing function.
 154 |     |      */
 155 |     |     function processProofCalldata(
 156 |     |         bytes32[] calldata proof,
 157 |     |         bytes32 leaf,
 158 |     |         function(bytes32, bytes32) view returns (bytes32) hasher
 159 |     |     ) internal view returns (bytes32) {
 160 |     |         bytes32 computedHash = leaf;
 161 |     |         for (uint256 i = 0; i < proof.length; i++) {
 162 |     |             computedHash = hasher(computedHash, proof[i]);
 163 |     |         }
 164 |     |         return computedHash;
 165 |     |     }
 166 |     | 
 167 |     |     /**
 168 |     |      * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
 169 |     |      * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
 170 |     |      *
 171 |     |      * This version handles multiproofs in memory with the default hashing function.
 172 |     |      *
 173 |     |      * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
 174 |     |      *
 175 |     |      * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
 176 |     |      * The `leaves` must be validated independently. See {processMultiProof}.
 177 |     |      */
 178 |     |     function multiProofVerify(
 179 |     |         bytes32[] memory proof,
 180 |     |         bool[] memory proofFlags,
 181 |     |         bytes32 root,
 182 |     |         bytes32[] memory leaves
 183 |     |     ) internal pure returns (bool) {
 184 |     |         return processMultiProof(proof, proofFlags, leaves) == root;
 185 |     |     }
 186 |     | 
 187 |     |     /**
 188 |     |      * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
 189 |     |      * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
 190 |     |      * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
 191 |     |      * respectively.
 192 |     |      *
 193 |     |      * This version handles multiproofs in memory with the default hashing function.
 194 |     |      *
 195 |     |      * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
 196 |     |      * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
 197 |     |      * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
 198 |     |      *
 199 |     |      * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
 200 |     |      * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
 201 |     |      * validating the leaves elsewhere.
 202 |     |      */
 203 |     |     function processMultiProof(
 204 |     |         bytes32[] memory proof,
 205 |     |         bool[] memory proofFlags,
 206 |     |         bytes32[] memory leaves
 207 |     |     ) internal pure returns (bytes32 merkleRoot) {
 208 |     |         // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
 209 |     |         // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
 210 |     |         // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
 211 |     |         // the Merkle tree.
 212 |     |         uint256 leavesLen = leaves.length;
 213 |     |         uint256 proofFlagsLen = proofFlags.length;
 214 |     | 
 215 |     |         // Check proof validity.
 216 |     |         if (leavesLen + proof.length != proofFlagsLen + 1) {
 217 |     |             revert MerkleProofInvalidMultiproof();
 218 |     |         }
 219 |     | 
 220 |     |         // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
 221 |     |         // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
 222 |     |         bytes32[] memory hashes = new bytes32[](proofFlagsLen);
 223 |     |         uint256 leafPos = 0;
 224 |     |         uint256 hashPos = 0;
 225 |     |         uint256 proofPos = 0;
 226 |     |         // At each step, we compute the next hash using two values:
 227 |     |         // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
 228 |     |         //   get the next hash.
 229 |     |         // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
 230 |     |         //   `proof` array.
 231 |     |         for (uint256 i = 0; i < proofFlagsLen; i++) {
 232 |     |             bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
 233 |     |             bytes32 b = proofFlags[i]
 234 |     |                 ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
 235 |     |                 : proof[proofPos++];
 236 |     |             hashes[i] = Hashes.commutativeKeccak256(a, b);
 237 |     |         }
 238 |     | 
 239 |     |         if (proofFlagsLen > 0) {
 240 |     |             if (proofPos != proof.length) {
 241 |     |                 revert MerkleProofInvalidMultiproof();
 242 |     |             }
 243 |     |             unchecked {
 244 |     |                 return hashes[proofFlagsLen - 1];
 245 |     |             }
 246 |     |         } else if (leavesLen > 0) {
 247 |     |             return leaves[0];
 248 |     |         } else {
 249 |     |             return proof[0];
 250 |     |         }
 251 |     |     }
 252 |     | 
 253 |     |     /**
 254 |     |      * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
 255 |     |      * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
 256 |     |      *
 257 |     |      * This version handles multiproofs in memory with a custom hashing function.
 258 |     |      *
 259 |     |      * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
 260 |     |      *
 261 |     |      * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
 262 |     |      * The `leaves` must be validated independently. See {processMultiProof}.
 263 |     |      */
 264 |     |     function multiProofVerify(
 265 |     |         bytes32[] memory proof,
 266 |     |         bool[] memory proofFlags,
 267 |     |         bytes32 root,
 268 |     |         bytes32[] memory leaves,
 269 |     |         function(bytes32, bytes32) view returns (bytes32) hasher
 270 |     |     ) internal view returns (bool) {
 271 |     |         return processMultiProof(proof, proofFlags, leaves, hasher) == root;
 272 |     |     }
 273 |     | 
 274 |     |     /**
 275 |     |      * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
 276 |     |      * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
 277 |     |      * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
 278 |     |      * respectively.
 279 |     |      *
 280 |     |      * This version handles multiproofs in memory with a custom hashing function.
 281 |     |      *
 282 |     |      * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
 283 |     |      * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
 284 |     |      * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
 285 |     |      *
 286 |     |      * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
 287 |     |      * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
 288 |     |      * validating the leaves elsewhere.
 289 |     |      */
 290 |     |     function processMultiProof(
 291 |     |         bytes32[] memory proof,
 292 |     |         bool[] memory proofFlags,
 293 |     |         bytes32[] memory leaves,
 294 |     |         function(bytes32, bytes32) view returns (bytes32) hasher
 295 |     |     ) internal view returns (bytes32 merkleRoot) {
 296 |     |         // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
 297 |     |         // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
 298 |     |         // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
 299 |     |         // the Merkle tree.
 300 |     |         uint256 leavesLen = leaves.length;
 301 |     |         uint256 proofFlagsLen = proofFlags.length;
 302 |     | 
 303 |     |         // Check proof validity.
 304 |     |         if (leavesLen + proof.length != proofFlagsLen + 1) {
 305 |     |             revert MerkleProofInvalidMultiproof();
 306 |     |         }
 307 |     | 
 308 |     |         // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
 309 |     |         // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
 310 |     |         bytes32[] memory hashes = new bytes32[](proofFlagsLen);
 311 |     |         uint256 leafPos = 0;
 312 |     |         uint256 hashPos = 0;
 313 |     |         uint256 proofPos = 0;
 314 |     |         // At each step, we compute the next hash using two values:
 315 |     |         // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
 316 |     |         //   get the next hash.
 317 |     |         // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
 318 |     |         //   `proof` array.
 319 |     |         for (uint256 i = 0; i < proofFlagsLen; i++) {
 320 |     |             bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
 321 |     |             bytes32 b = proofFlags[i]
 322 |     |                 ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
 323 |     |                 : proof[proofPos++];
 324 |     |             hashes[i] = hasher(a, b);
 325 |     |         }
 326 |     | 
 327 |     |         if (proofFlagsLen > 0) {
 328 |     |             if (proofPos != proof.length) {
 329 |     |                 revert MerkleProofInvalidMultiproof();
 330 |     |             }
 331 |     |             unchecked {
 332 |     |                 return hashes[proofFlagsLen - 1];
 333 |     |             }
 334 |     |         } else if (leavesLen > 0) {
 335 |     |             return leaves[0];
 336 |     |         } else {
 337 |     |             return proof[0];
 338 |     |         }
 339 |     |     }
 340 |     | 
 341 |     |     /**
 342 |     |      * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
 343 |     |      * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
 344 |     |      *
 345 |     |      * This version handles multiproofs in calldata with the default hashing function.
 346 |     |      *
 347 |     |      * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
 348 |     |      *
 349 |     |      * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
 350 |     |      * The `leaves` must be validated independently. See {processMultiProofCalldata}.
 351 |     |      */
 352 |     |     function multiProofVerifyCalldata(
 353 |     |         bytes32[] calldata proof,
 354 |     |         bool[] calldata proofFlags,
 355 |     |         bytes32 root,
 356 |     |         bytes32[] memory leaves
 357 |     |     ) internal pure returns (bool) {
 358 |     |         return processMultiProofCalldata(proof, proofFlags, leaves) == root;
 359 |     |     }
 360 |     | 
 361 |     |     /**
 362 |     |      * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
 363 |     |      * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
 364 |     |      * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
 365 |     |      * respectively.
 366 |     |      *
 367 |     |      * This version handles multiproofs in calldata with the default hashing function.
 368 |     |      *
 369 |     |      * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
 370 |     |      * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
 371 |     |      * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
 372 |     |      *
 373 |     |      * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
 374 |     |      * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
 375 |     |      * validating the leaves elsewhere.
 376 |     |      */
 377 |     |     function processMultiProofCalldata(
 378 |     |         bytes32[] calldata proof,
 379 |     |         bool[] calldata proofFlags,
 380 |     |         bytes32[] memory leaves
 381 |     |     ) internal pure returns (bytes32 merkleRoot) {
 382 |     |         // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
 383 |     |         // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
 384 |     |         // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
 385 |     |         // the Merkle tree.
 386 |     |         uint256 leavesLen = leaves.length;
 387 |     |         uint256 proofFlagsLen = proofFlags.length;
 388 |     | 
 389 |     |         // Check proof validity.
 390 |     |         if (leavesLen + proof.length != proofFlagsLen + 1) {
 391 |     |             revert MerkleProofInvalidMultiproof();
 392 |     |         }
 393 |     | 
 394 |     |         // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
 395 |     |         // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
 396 |     |         bytes32[] memory hashes = new bytes32[](proofFlagsLen);
 397 |     |         uint256 leafPos = 0;
 398 |     |         uint256 hashPos = 0;
 399 |     |         uint256 proofPos = 0;
 400 |     |         // At each step, we compute the next hash using two values:
 401 |     |         // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
 402 |     |         //   get the next hash.
 403 |     |         // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
 404 |     |         //   `proof` array.
 405 |     |         for (uint256 i = 0; i < proofFlagsLen; i++) {
 406 |     |             bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
 407 |     |             bytes32 b = proofFlags[i]
 408 |     |                 ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
 409 |     |                 : proof[proofPos++];
 410 |     |             hashes[i] = Hashes.commutativeKeccak256(a, b);
 411 |     |         }
 412 |     | 
 413 |     |         if (proofFlagsLen > 0) {
 414 |     |             if (proofPos != proof.length) {
 415 |     |                 revert MerkleProofInvalidMultiproof();
 416 |     |             }
 417 |     |             unchecked {
 418 |     |                 return hashes[proofFlagsLen - 1];
 419 |     |             }
 420 |     |         } else if (leavesLen > 0) {
 421 |     |             return leaves[0];
 422 |     |         } else {
 423 |     |             return proof[0];
 424 |     |         }
 425 |     |     }
 426 |     | 
 427 |     |     /**
 428 |     |      * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
 429 |     |      * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
 430 |     |      *
 431 |     |      * This version handles multiproofs in calldata with a custom hashing function.
 432 |     |      *
 433 |     |      * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
 434 |     |      *
 435 |     |      * NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
 436 |     |      * The `leaves` must be validated independently. See {processMultiProofCalldata}.
 437 |     |      */
 438 |     |     function multiProofVerifyCalldata(
 439 |     |         bytes32[] calldata proof,
 440 |     |         bool[] calldata proofFlags,
 441 |     |         bytes32 root,
 442 |     |         bytes32[] memory leaves,
 443 |     |         function(bytes32, bytes32) view returns (bytes32) hasher
 444 |     |     ) internal view returns (bool) {
 445 |     |         return processMultiProofCalldata(proof, proofFlags, leaves, hasher) == root;
 446 |     |     }
 447 |     | 
 448 |     |     /**
 449 |     |      * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
 450 |     |      * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
 451 |     |      * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
 452 |     |      * respectively.
 453 |     |      *
 454 |     |      * This version handles multiproofs in calldata with a custom hashing function.
 455 |     |      *
 456 |     |      * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
 457 |     |      * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
 458 |     |      * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
 459 |     |      *
 460 |     |      * NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
 461 |     |      * and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
 462 |     |      * validating the leaves elsewhere.
 463 |     |      */
 464 |     |     function processMultiProofCalldata(
 465 |     |         bytes32[] calldata proof,
 466 |     |         bool[] calldata proofFlags,
 467 |     |         bytes32[] memory leaves,
 468 |     |         function(bytes32, bytes32) view returns (bytes32) hasher
 469 |     |     ) internal view returns (bytes32 merkleRoot) {
 470 |     |         // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
 471 |     |         // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
 472 |     |         // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
 473 |     |         // the Merkle tree.
 474 |     |         uint256 leavesLen = leaves.length;
 475 |     |         uint256 proofFlagsLen = proofFlags.length;
 476 |     | 
 477 |     |         // Check proof validity.
 478 |     |         if (leavesLen + proof.length != proofFlagsLen + 1) {
 479 |     |             revert MerkleProofInvalidMultiproof();
 480 |     |         }
 481 |     | 
 482 |     |         // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
 483 |     |         // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
 484 |     |         bytes32[] memory hashes = new bytes32[](proofFlagsLen);
 485 |     |         uint256 leafPos = 0;
 486 |     |         uint256 hashPos = 0;
 487 |     |         uint256 proofPos = 0;
 488 |     |         // At each step, we compute the next hash using two values:
 489 |     |         // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
 490 |     |         //   get the next hash.
 491 |     |         // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
 492 |     |         //   `proof` array.
 493 |     |         for (uint256 i = 0; i < proofFlagsLen; i++) {
 494 |     |             bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
 495 |     |             bytes32 b = proofFlags[i]
 496 |     |                 ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
 497 |     |                 : proof[proofPos++];
 498 |     |             hashes[i] = hasher(a, b);
 499 |     |         }
 500 |     | 
 501 |     |         if (proofFlagsLen > 0) {
 502 |     |             if (proofPos != proof.length) {
 503 |     |                 revert MerkleProofInvalidMultiproof();
 504 |     |             }
 505 |     |             unchecked {
 506 |     |                 return hashes[proofFlagsLen - 1];
 507 |     |             }
 508 |     |         } else if (leavesLen > 0) {
 509 |     |             return leaves[0];
 510 |     |         } else {
 511 |     |             return proof[0];
 512 |     |         }
 513 |     |     }
 514 |     | }
 515 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | import {Strings} from "../Strings.sol";
   7 |     | 
   8 |     | /**
   9 |     |  * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
  10 |     |  *
  11 |     |  * The library provides methods for generating a hash of a message that conforms to the
  12 |     |  * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
  13 |     |  * specifications.
  14 |     |  */
  15 |     | library MessageHashUtils {
  16 |     |     /**
  17 |     |      * @dev Returns the keccak256 digest of an ERC-191 signed data with version
  18 |     |      * `0x45` (`personal_sign` messages).
  19 |     |      *
  20 |     |      * The digest is calculated by prefixing a bytes32 `messageHash` with
  21 |     |      * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
  22 |     |      * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
  23 |     |      *
  24 |     |      * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
  25 |     |      * keccak256, although any bytes32 value can be safely used because the final digest will
  26 |     |      * be re-hashed.
  27 |     |      *
  28 |     |      * See {ECDSA-recover}.
  29 |     |      */
  30 |     |     function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
  31 |     |         assembly ("memory-safe") {
  32 |     |             mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
  33 |     |             mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
  34 |     |             digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
  35 |     |         }
  36 |     |     }
  37 |     | 
  38 |     |     /**
  39 |     |      * @dev Returns the keccak256 digest of an ERC-191 signed data with version
  40 |     |      * `0x45` (`personal_sign` messages).
  41 |     |      *
  42 |     |      * The digest is calculated by prefixing an arbitrary `message` with
  43 |     |      * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
  44 |     |      * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
  45 |     |      *
  46 |     |      * See {ECDSA-recover}.
  47 |     |      */
  48 |     |     function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
  49 |     |         return
  50 |     |             keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
  51 |     |     }
  52 |     | 
  53 |     |     /**
  54 |     |      * @dev Returns the keccak256 digest of an ERC-191 signed data with version
  55 |     |      * `0x00` (data with intended validator).
  56 |     |      *
  57 |     |      * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
  58 |     |      * `validator` address. Then hashing the result.
  59 |     |      *
  60 |     |      * See {ECDSA-recover}.
  61 |     |      */
  62 |     |     function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
  63 |     |         return keccak256(abi.encodePacked(hex"19_00", validator, data));
  64 |     |     }
  65 |     | 
  66 |     |     /**
  67 |     |      * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.
  68 |     |      */
  69 |     |     function toDataWithIntendedValidatorHash(
  70 |     |         address validator,
  71 |     |         bytes32 messageHash
  72 |     |     ) internal pure returns (bytes32 digest) {
  73 |     |         assembly ("memory-safe") {
  74 |     |             mstore(0x00, hex"19_00")
  75 |     |             mstore(0x02, shl(96, validator))
  76 |     |             mstore(0x16, messageHash)
  77 |     |             digest := keccak256(0x00, 0x36)
  78 |     |         }
  79 |     |     }
  80 |     | 
  81 |     |     /**
  82 |     |      * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).
  83 |     |      *
  84 |     |      * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
  85 |     |      * `\x19\x01` and hashing the result. It corresponds to the hash signed by the
  86 |     |      * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
  87 |     |      *
  88 |     |      * See {ECDSA-recover}.
  89 |     |      */
  90 |     |     function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
  91 |     |         assembly ("memory-safe") {
  92 |     |             let ptr := mload(0x40)
  93 |     |             mstore(ptr, hex"19_01")
  94 |     |             mstore(add(ptr, 0x02), domainSeparator)
  95 |     |             mstore(add(ptr, 0x22), structHash)
  96 |     |             digest := keccak256(ptr, 0x42)
  97 |     |         }
  98 |     |     }
  99 |     | }
 100 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | 
  6 |     | import {IERC165} from "./IERC165.sol";
  7 |     | 
  8 |     | /**
  9 |     |  * @dev Implementation of the {IERC165} interface.
 10 |     |  *
 11 |     |  * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
 12 |     |  * for the additional interface id that will be supported. For example:
 13 |     |  *
 14 |     |  * ```solidity
 15 |     |  * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 16 |     |  *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 17 |     |  * }
 18 |     |  * ```
 19 |     |  */
 20 |     | abstract contract ERC165 is IERC165 {
 21 |     |     /// @inheritdoc IERC165
 22 |     |     function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
 23 |     |         return interfaceId == type(IERC165).interfaceId;
 24 |     |     }
 25 |     | }
 26 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
  3 |     | 
  4 |     | pragma solidity >=0.4.16;
  5 |     | 
  6 |     | /**
  7 |     |  * @dev Interface of the ERC-165 standard, as defined in the
  8 |     |  * https://eips.ethereum.org/EIPS/eip-165[ERC].
  9 |     |  *
 10 |     |  * Implementers can declare support of contract interfaces, which can then be
 11 |     |  * queried by others ({ERC165Checker}).
 12 |     |  *
 13 |     |  * For an implementation, see {ERC165}.
 14 |     |  */
 15 |     | interface IERC165 {
 16 |     |     /**
 17 |     |      * @dev Returns true if this contract implements the interface defined by
 18 |     |      * `interfaceId`. See the corresponding
 19 |     |      * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
 20 |     |      * to learn more about how these ids are created.
 21 |     |      *
 22 |     |      * This function call must use less than 30 000 gas.
 23 |     |      */
 24 |     |     function supportsInterface(bytes4 interfaceId) external view returns (bool);
 25 |     | }
 26 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/math/Math.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
   3 |     | 
   4 |     | pragma solidity ^0.8.20;
   5 |     | 
   6 |     | import {Panic} from "../Panic.sol";
   7 |     | import {SafeCast} from "./SafeCast.sol";
   8 |     | 
   9 |     | /**
  10 |     |  * @dev Standard math utilities missing in the Solidity language.
  11 |     |  */
  12 |     | library Math {
  13 |     |     enum Rounding {
  14 |     |         Floor, // Toward negative infinity
  15 |     |         Ceil, // Toward positive infinity
  16 |     |         Trunc, // Toward zero
  17 |     |         Expand // Away from zero
  18 |     |     }
  19 |     | 
  20 |     |     /**
  21 |     |      * @dev Return the 512-bit addition of two uint256.
  22 |     |      *
  23 |     |      * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
  24 |     |      */
  25 |     |     function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
  26 |     |         assembly ("memory-safe") {
  27 |     |             low := add(a, b)
  28 |     |             high := lt(low, a)
  29 |     |         }
  30 |     |     }
  31 |     | 
  32 |     |     /**
  33 |     |      * @dev Return the 512-bit multiplication of two uint256.
  34 |     |      *
  35 |     |      * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
  36 |     |      */
  37 | *   |     function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
  38 |     |         // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
  39 |     |         // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
  40 |     |         // variables such that product = high * 2²⁵⁶ + low.
  41 |     |         assembly ("memory-safe") {
  42 | *   |             let mm := mulmod(a, b, not(0))
  43 | *   |             low := mul(a, b)
  44 | *   |             high := sub(sub(mm, low), lt(mm, low))
  45 |     |         }
  46 |     |     }
  47 |     | 
  48 |     |     /**
  49 |     |      * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
  50 |     |      */
  51 |     |     function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
  52 |     |         unchecked {
  53 |     |             uint256 c = a + b;
  54 |     |             success = c >= a;
  55 |     |             result = c * SafeCast.toUint(success);
  56 |     |         }
  57 |     |     }
  58 |     | 
  59 |     |     /**
  60 |     |      * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
  61 |     |      */
  62 |     |     function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
  63 |     |         unchecked {
  64 |     |             uint256 c = a - b;
  65 |     |             success = c <= a;
  66 |     |             result = c * SafeCast.toUint(success);
  67 |     |         }
  68 |     |     }
  69 |     | 
  70 |     |     /**
  71 |     |      * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
  72 |     |      */
  73 |     |     function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
  74 |     |         unchecked {
  75 |     |             uint256 c = a * b;
  76 |     |             assembly ("memory-safe") {
  77 |     |                 // Only true when the multiplication doesn't overflow
  78 |     |                 // (c / a == b) || (a == 0)
  79 |     |                 success := or(eq(div(c, a), b), iszero(a))
  80 |     |             }
  81 |     |             // equivalent to: success ? c : 0
  82 |     |             result = c * SafeCast.toUint(success);
  83 |     |         }
  84 |     |     }
  85 |     | 
  86 |     |     /**
  87 |     |      * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
  88 |     |      */
  89 |     |     function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
  90 |     |         unchecked {
  91 |     |             success = b > 0;
  92 |     |             assembly ("memory-safe") {
  93 |     |                 // The `DIV` opcode returns zero when the denominator is 0.
  94 |     |                 result := div(a, b)
  95 |     |             }
  96 |     |         }
  97 |     |     }
  98 |     | 
  99 |     |     /**
 100 |     |      * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
 101 |     |      */
 102 |     |     function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
 103 |     |         unchecked {
 104 |     |             success = b > 0;
 105 |     |             assembly ("memory-safe") {
 106 |     |                 // The `MOD` opcode returns zero when the denominator is 0.
 107 |     |                 result := mod(a, b)
 108 |     |             }
 109 |     |         }
 110 |     |     }
 111 |     | 
 112 |     |     /**
 113 |     |      * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
 114 |     |      */
 115 |     |     function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
 116 |     |         (bool success, uint256 result) = tryAdd(a, b);
 117 |     |         return ternary(success, result, type(uint256).max);
 118 |     |     }
 119 |     | 
 120 |     |     /**
 121 |     |      * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
 122 |     |      */
 123 |     |     function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
 124 |     |         (, uint256 result) = trySub(a, b);
 125 |     |         return result;
 126 |     |     }
 127 |     | 
 128 |     |     /**
 129 |     |      * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
 130 |     |      */
 131 |     |     function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
 132 |     |         (bool success, uint256 result) = tryMul(a, b);
 133 |     |         return ternary(success, result, type(uint256).max);
 134 |     |     }
 135 |     | 
 136 |     |     /**
 137 |     |      * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
 138 |     |      *
 139 |     |      * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
 140 |     |      * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
 141 |     |      * one branch when needed, making this function more expensive.
 142 |     |      */
 143 |     |     function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
 144 |     |         unchecked {
 145 |     |             // branchless ternary works because:
 146 |     |             // b ^ (a ^ b) == a
 147 |     |             // b ^ 0 == b
 148 | *   |             return b ^ ((a ^ b) * SafeCast.toUint(condition));
 149 |     |         }
 150 |     |     }
 151 |     | 
 152 |     |     /**
 153 |     |      * @dev Returns the largest of two numbers.
 154 |     |      */
 155 |     |     function max(uint256 a, uint256 b) internal pure returns (uint256) {
 156 |     |         return ternary(a > b, a, b);
 157 |     |     }
 158 |     | 
 159 |     |     /**
 160 |     |      * @dev Returns the smallest of two numbers.
 161 |     |      */
 162 |     |     function min(uint256 a, uint256 b) internal pure returns (uint256) {
 163 |     |         return ternary(a < b, a, b);
 164 |     |     }
 165 |     | 
 166 |     |     /**
 167 |     |      * @dev Returns the average of two numbers. The result is rounded towards
 168 |     |      * zero.
 169 |     |      */
 170 |     |     function average(uint256 a, uint256 b) internal pure returns (uint256) {
 171 |     |         // (a + b) / 2 can overflow.
 172 |     |         return (a & b) + (a ^ b) / 2;
 173 |     |     }
 174 |     | 
 175 |     |     /**
 176 |     |      * @dev Returns the ceiling of the division of two numbers.
 177 |     |      *
 178 |     |      * This differs from standard division with `/` in that it rounds towards infinity instead
 179 |     |      * of rounding towards zero.
 180 |     |      */
 181 |     |     function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
 182 |     |         if (b == 0) {
 183 |     |             // Guarantee the same behavior as in a regular Solidity division.
 184 |     |             Panic.panic(Panic.DIVISION_BY_ZERO);
 185 |     |         }
 186 |     | 
 187 |     |         // The following calculation ensures accurate ceiling division without overflow.
 188 |     |         // Since a is non-zero, (a - 1) / b will not overflow.
 189 |     |         // The largest possible result occurs when (a - 1) / b is type(uint256).max,
 190 |     |         // but the largest value we can obtain is type(uint256).max - 1, which happens
 191 |     |         // when a = type(uint256).max and b = 1.
 192 |     |         unchecked {
 193 |     |             return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
 194 |     |         }
 195 |     |     }
 196 |     | 
 197 |     |     /**
 198 |     |      * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
 199 |     |      * denominator == 0.
 200 |     |      *
 201 |     |      * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
 202 |     |      * Uniswap Labs also under MIT license.
 203 |     |      */
 204 | *   |     function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
 205 |     |         unchecked {
 206 | *   |             (uint256 high, uint256 low) = mul512(x, y);
 207 |     | 
 208 |     |             // Handle non-overflow cases, 256 by 256 division.
 209 | *   |             if (high == 0) {
 210 |     |                 // Solidity will revert if denominator == 0, unlike the div opcode on its own.
 211 |     |                 // The surrounding unchecked block does not change this fact.
 212 |     |                 // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
 213 | *   |                 return low / denominator;
 214 |     |             }
 215 |     | 
 216 |     |             // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
 217 | *   |             if (denominator <= high) {
 218 | *   |                 Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
 219 |     |             }
 220 |     | 
 221 |     |             ///////////////////////////////////////////////
 222 |     |             // 512 by 256 division.
 223 |     |             ///////////////////////////////////////////////
 224 |     | 
 225 |     |             // Make division exact by subtracting the remainder from [high low].
 226 | *   |             uint256 remainder;
 227 |     |             assembly ("memory-safe") {
 228 |     |                 // Compute remainder using mulmod.
 229 | *   |                 remainder := mulmod(x, y, denominator)
 230 |     | 
 231 |     |                 // Subtract 256 bit number from 512 bit number.
 232 | *   |                 high := sub(high, gt(remainder, low))
 233 | *   |                 low := sub(low, remainder)
 234 |     |             }
 235 |     | 
 236 |     |             // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
 237 |     |             // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
 238 |     | 
 239 | *   |             uint256 twos = denominator & (0 - denominator);
 240 |     |             assembly ("memory-safe") {
 241 |     |                 // Divide denominator by twos.
 242 | *   |                 denominator := div(denominator, twos)
 243 |     | 
 244 |     |                 // Divide [high low] by twos.
 245 | *   |                 low := div(low, twos)
 246 |     | 
 247 |     |                 // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
 248 | *   |                 twos := add(div(sub(0, twos), twos), 1)
 249 |     |             }
 250 |     | 
 251 |     |             // Shift in bits from high into low.
 252 | *   |             low |= high * twos;
 253 |     | 
 254 |     |             // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
 255 |     |             // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
 256 |     |             // four bits. That is, denominator * inv ≡ 1 mod 2⁴.
 257 | *   |             uint256 inverse = (3 * denominator) ^ 2;
 258 |     | 
 259 |     |             // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
 260 |     |             // works in modular arithmetic, doubling the correct bits in each step.
 261 | *   |             inverse *= 2 - denominator * inverse; // inverse mod 2⁸
 262 | *   |             inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
 263 | *   |             inverse *= 2 - denominator * inverse; // inverse mod 2³²
 264 | *   |             inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
 265 | *   |             inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
 266 | *   |             inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
 267 |     | 
 268 |     |             // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
 269 |     |             // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
 270 |     |             // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
 271 |     |             // is no longer required.
 272 | *   |             result = low * inverse;
 273 |     |             return result;
 274 |     |         }
 275 |     |     }
 276 |     | 
 277 |     |     /**
 278 |     |      * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
 279 |     |      */
 280 | *   |     function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
 281 | *   |         return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
 282 |     |     }
 283 |     | 
 284 |     |     /**
 285 |     |      * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
 286 |     |      */
 287 |     |     function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
 288 |     |         unchecked {
 289 |     |             (uint256 high, uint256 low) = mul512(x, y);
 290 |     |             if (high >= 1 << n) {
 291 |     |                 Panic.panic(Panic.UNDER_OVERFLOW);
 292 |     |             }
 293 |     |             return (high << (256 - n)) | (low >> n);
 294 |     |         }
 295 |     |     }
 296 |     | 
 297 |     |     /**
 298 |     |      * @dev Calculates x * y >> n with full precision, following the selected rounding direction.
 299 |     |      */
 300 |     |     function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
 301 |     |         return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
 302 |     |     }
 303 |     | 
 304 |     |     /**
 305 |     |      * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
 306 |     |      *
 307 |     |      * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
 308 |     |      * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
 309 |     |      *
 310 |     |      * If the input value is not inversible, 0 is returned.
 311 |     |      *
 312 |     |      * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
 313 |     |      * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
 314 |     |      */
 315 |     |     function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
 316 |     |         unchecked {
 317 |     |             if (n == 0) return 0;
 318 |     | 
 319 |     |             // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
 320 |     |             // Used to compute integers x and y such that: ax + ny = gcd(a, n).
 321 |     |             // When the gcd is 1, then the inverse of a modulo n exists and it's x.
 322 |     |             // ax + ny = 1
 323 |     |             // ax = 1 + (-y)n
 324 |     |             // ax ≡ 1 (mod n) # x is the inverse of a modulo n
 325 |     | 
 326 |     |             // If the remainder is 0 the gcd is n right away.
 327 |     |             uint256 remainder = a % n;
 328 |     |             uint256 gcd = n;
 329 |     | 
 330 |     |             // Therefore the initial coefficients are:
 331 |     |             // ax + ny = gcd(a, n) = n
 332 |     |             // 0a + 1n = n
 333 |     |             int256 x = 0;
 334 |     |             int256 y = 1;
 335 |     | 
 336 |     |             while (remainder != 0) {
 337 |     |                 uint256 quotient = gcd / remainder;
 338 |     | 
 339 |     |                 (gcd, remainder) = (
 340 |     |                     // The old remainder is the next gcd to try.
 341 |     |                     remainder,
 342 |     |                     // Compute the next remainder.
 343 |     |                     // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
 344 |     |                     // where gcd is at most n (capped to type(uint256).max)
 345 |     |                     gcd - remainder * quotient
 346 |     |                 );
 347 |     | 
 348 |     |                 (x, y) = (
 349 |     |                     // Increment the coefficient of a.
 350 |     |                     y,
 351 |     |                     // Decrement the coefficient of n.
 352 |     |                     // Can overflow, but the result is casted to uint256 so that the
 353 |     |                     // next value of y is "wrapped around" to a value between 0 and n - 1.
 354 |     |                     x - y * int256(quotient)
 355 |     |                 );
 356 |     |             }
 357 |     | 
 358 |     |             if (gcd != 1) return 0; // No inverse exists.
 359 |     |             return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
 360 |     |         }
 361 |     |     }
 362 |     | 
 363 |     |     /**
 364 |     |      * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
 365 |     |      *
 366 |     |      * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
 367 |     |      * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
 368 |     |      * `a**(p-2)` is the modular multiplicative inverse of a in Fp.
 369 |     |      *
 370 |     |      * NOTE: this function does NOT check that `p` is a prime greater than `2`.
 371 |     |      */
 372 |     |     function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
 373 |     |         unchecked {
 374 |     |             return Math.modExp(a, p - 2, p);
 375 |     |         }
 376 |     |     }
 377 |     | 
 378 |     |     /**
 379 |     |      * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
 380 |     |      *
 381 |     |      * Requirements:
 382 |     |      * - modulus can't be zero
 383 |     |      * - underlying staticcall to precompile must succeed
 384 |     |      *
 385 |     |      * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
 386 |     |      * sure the chain you're using it on supports the precompiled contract for modular exponentiation
 387 |     |      * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
 388 |     |      * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
 389 |     |      * interpreted as 0.
 390 |     |      */
 391 |     |     function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
 392 |     |         (bool success, uint256 result) = tryModExp(b, e, m);
 393 |     |         if (!success) {
 394 |     |             Panic.panic(Panic.DIVISION_BY_ZERO);
 395 |     |         }
 396 |     |         return result;
 397 |     |     }
 398 |     | 
 399 |     |     /**
 400 |     |      * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
 401 |     |      * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
 402 |     |      * to operate modulo 0 or if the underlying precompile reverted.
 403 |     |      *
 404 |     |      * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
 405 |     |      * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
 406 |     |      * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
 407 |     |      * of a revert, but the result may be incorrectly interpreted as 0.
 408 |     |      */
 409 |     |     function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
 410 |     |         if (m == 0) return (false, 0);
 411 |     |         assembly ("memory-safe") {
 412 |     |             let ptr := mload(0x40)
 413 |     |             // | Offset    | Content    | Content (Hex)                                                      |
 414 |     |             // |-----------|------------|--------------------------------------------------------------------|
 415 |     |             // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
 416 |     |             // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
 417 |     |             // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
 418 |     |             // | 0x60:0x7f | value of b | 0x<.............................................................b> |
 419 |     |             // | 0x80:0x9f | value of e | 0x<.............................................................e> |
 420 |     |             // | 0xa0:0xbf | value of m | 0x<.............................................................m> |
 421 |     |             mstore(ptr, 0x20)
 422 |     |             mstore(add(ptr, 0x20), 0x20)
 423 |     |             mstore(add(ptr, 0x40), 0x20)
 424 |     |             mstore(add(ptr, 0x60), b)
 425 |     |             mstore(add(ptr, 0x80), e)
 426 |     |             mstore(add(ptr, 0xa0), m)
 427 |     | 
 428 |     |             // Given the result < m, it's guaranteed to fit in 32 bytes,
 429 |     |             // so we can use the memory scratch space located at offset 0.
 430 |     |             success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
 431 |     |             result := mload(0x00)
 432 |     |         }
 433 |     |     }
 434 |     | 
 435 |     |     /**
 436 |     |      * @dev Variant of {modExp} that supports inputs of arbitrary length.
 437 |     |      */
 438 |     |     function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
 439 |     |         (bool success, bytes memory result) = tryModExp(b, e, m);
 440 |     |         if (!success) {
 441 |     |             Panic.panic(Panic.DIVISION_BY_ZERO);
 442 |     |         }
 443 |     |         return result;
 444 |     |     }
 445 |     | 
 446 |     |     /**
 447 |     |      * @dev Variant of {tryModExp} that supports inputs of arbitrary length.
 448 |     |      */
 449 |     |     function tryModExp(
 450 |     |         bytes memory b,
 451 |     |         bytes memory e,
 452 |     |         bytes memory m
 453 |     |     ) internal view returns (bool success, bytes memory result) {
 454 |     |         if (_zeroBytes(m)) return (false, new bytes(0));
 455 |     | 
 456 |     |         uint256 mLen = m.length;
 457 |     | 
 458 |     |         // Encode call args in result and move the free memory pointer
 459 |     |         result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
 460 |     | 
 461 |     |         assembly ("memory-safe") {
 462 |     |             let dataPtr := add(result, 0x20)
 463 |     |             // Write result on top of args to avoid allocating extra memory.
 464 |     |             success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
 465 |     |             // Overwrite the length.
 466 |     |             // result.length > returndatasize() is guaranteed because returndatasize() == m.length
 467 |     |             mstore(result, mLen)
 468 |     |             // Set the memory pointer after the returned data.
 469 |     |             mstore(0x40, add(dataPtr, mLen))
 470 |     |         }
 471 |     |     }
 472 |     | 
 473 |     |     /**
 474 |     |      * @dev Returns whether the provided byte array is zero.
 475 |     |      */
 476 |     |     function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
 477 |     |         for (uint256 i = 0; i < byteArray.length; ++i) {
 478 |     |             if (byteArray[i] != 0) {
 479 |     |                 return false;
 480 |     |             }
 481 |     |         }
 482 |     |         return true;
 483 |     |     }
 484 |     | 
 485 |     |     /**
 486 |     |      * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
 487 |     |      * towards zero.
 488 |     |      *
 489 |     |      * This method is based on Newton's method for computing square roots; the algorithm is restricted to only
 490 |     |      * using integer operations.
 491 |     |      */
 492 |     |     function sqrt(uint256 a) internal pure returns (uint256) {
 493 |     |         unchecked {
 494 |     |             // Take care of easy edge cases when a == 0 or a == 1
 495 |     |             if (a <= 1) {
 496 |     |                 return a;
 497 |     |             }
 498 |     | 
 499 |     |             // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
 500 |     |             // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
 501 |     |             // the current value as `ε_n = | x_n - sqrt(a) |`.
 502 |     |             //
 503 |     |             // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
 504 |     |             // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
 505 |     |             // bigger than any uint256.
 506 |     |             //
 507 |     |             // By noticing that
 508 |     |             // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
 509 |     |             // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
 510 |     |             // to the msb function.
 511 |     |             uint256 aa = a;
 512 |     |             uint256 xn = 1;
 513 |     | 
 514 |     |             if (aa >= (1 << 128)) {
 515 |     |                 aa >>= 128;
 516 |     |                 xn <<= 64;
 517 |     |             }
 518 |     |             if (aa >= (1 << 64)) {
 519 |     |                 aa >>= 64;
 520 |     |                 xn <<= 32;
 521 |     |             }
 522 |     |             if (aa >= (1 << 32)) {
 523 |     |                 aa >>= 32;
 524 |     |                 xn <<= 16;
 525 |     |             }
 526 |     |             if (aa >= (1 << 16)) {
 527 |     |                 aa >>= 16;
 528 |     |                 xn <<= 8;
 529 |     |             }
 530 |     |             if (aa >= (1 << 8)) {
 531 |     |                 aa >>= 8;
 532 |     |                 xn <<= 4;
 533 |     |             }
 534 |     |             if (aa >= (1 << 4)) {
 535 |     |                 aa >>= 4;
 536 |     |                 xn <<= 2;
 537 |     |             }
 538 |     |             if (aa >= (1 << 2)) {
 539 |     |                 xn <<= 1;
 540 |     |             }
 541 |     | 
 542 |     |             // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
 543 |     |             //
 544 |     |             // We can refine our estimation by noticing that the middle of that interval minimizes the error.
 545 |     |             // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
 546 |     |             // This is going to be our x_0 (and ε_0)
 547 |     |             xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
 548 |     | 
 549 |     |             // From here, Newton's method give us:
 550 |     |             // x_{n+1} = (x_n + a / x_n) / 2
 551 |     |             //
 552 |     |             // One should note that:
 553 |     |             // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
 554 |     |             //              = ((x_n² + a) / (2 * x_n))² - a
 555 |     |             //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
 556 |     |             //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
 557 |     |             //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
 558 |     |             //              = (x_n² - a)² / (2 * x_n)²
 559 |     |             //              = ((x_n² - a) / (2 * x_n))²
 560 |     |             //              ≥ 0
 561 |     |             // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
 562 |     |             //
 563 |     |             // This gives us the proof of quadratic convergence of the sequence:
 564 |     |             // ε_{n+1} = | x_{n+1} - sqrt(a) |
 565 |     |             //         = | (x_n + a / x_n) / 2 - sqrt(a) |
 566 |     |             //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
 567 |     |             //         = | (x_n - sqrt(a))² / (2 * x_n) |
 568 |     |             //         = | ε_n² / (2 * x_n) |
 569 |     |             //         = ε_n² / | (2 * x_n) |
 570 |     |             //
 571 |     |             // For the first iteration, we have a special case where x_0 is known:
 572 |     |             // ε_1 = ε_0² / | (2 * x_0) |
 573 |     |             //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
 574 |     |             //     ≤ 2**(2*e-4) / (3 * 2**(e-1))
 575 |     |             //     ≤ 2**(e-3) / 3
 576 |     |             //     ≤ 2**(e-3-log2(3))
 577 |     |             //     ≤ 2**(e-4.5)
 578 |     |             //
 579 |     |             // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
 580 |     |             // ε_{n+1} = ε_n² / | (2 * x_n) |
 581 |     |             //         ≤ (2**(e-k))² / (2 * 2**(e-1))
 582 |     |             //         ≤ 2**(2*e-2*k) / 2**e
 583 |     |             //         ≤ 2**(e-2*k)
 584 |     |             xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above
 585 |     |             xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5
 586 |     |             xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9
 587 |     |             xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18
 588 |     |             xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36
 589 |     |             xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72
 590 |     | 
 591 |     |             // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
 592 |     |             // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
 593 |     |             // sqrt(a) or sqrt(a) + 1.
 594 |     |             return xn - SafeCast.toUint(xn > a / xn);
 595 |     |         }
 596 |     |     }
 597 |     | 
 598 |     |     /**
 599 |     |      * @dev Calculates sqrt(a), following the selected rounding direction.
 600 |     |      */
 601 |     |     function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
 602 |     |         unchecked {
 603 |     |             uint256 result = sqrt(a);
 604 |     |             return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
 605 |     |         }
 606 |     |     }
 607 |     | 
 608 |     |     /**
 609 |     |      * @dev Return the log in base 2 of a positive value rounded towards zero.
 610 |     |      * Returns 0 if given 0.
 611 |     |      */
 612 |     |     function log2(uint256 x) internal pure returns (uint256 r) {
 613 |     |         // If value has upper 128 bits set, log2 result is at least 128
 614 |     |         r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
 615 |     |         // If upper 64 bits of 128-bit half set, add 64 to result
 616 |     |         r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
 617 |     |         // If upper 32 bits of 64-bit half set, add 32 to result
 618 |     |         r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
 619 |     |         // If upper 16 bits of 32-bit half set, add 16 to result
 620 |     |         r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
 621 |     |         // If upper 8 bits of 16-bit half set, add 8 to result
 622 |     |         r |= SafeCast.toUint((x >> r) > 0xff) << 3;
 623 |     |         // If upper 4 bits of 8-bit half set, add 4 to result
 624 |     |         r |= SafeCast.toUint((x >> r) > 0xf) << 2;
 625 |     | 
 626 |     |         // Shifts value right by the current result and use it as an index into this lookup table:
 627 |     |         //
 628 |     |         // | x (4 bits) |  index  | table[index] = MSB position |
 629 |     |         // |------------|---------|-----------------------------|
 630 |     |         // |    0000    |    0    |        table[0] = 0         |
 631 |     |         // |    0001    |    1    |        table[1] = 0         |
 632 |     |         // |    0010    |    2    |        table[2] = 1         |
 633 |     |         // |    0011    |    3    |        table[3] = 1         |
 634 |     |         // |    0100    |    4    |        table[4] = 2         |
 635 |     |         // |    0101    |    5    |        table[5] = 2         |
 636 |     |         // |    0110    |    6    |        table[6] = 2         |
 637 |     |         // |    0111    |    7    |        table[7] = 2         |
 638 |     |         // |    1000    |    8    |        table[8] = 3         |
 639 |     |         // |    1001    |    9    |        table[9] = 3         |
 640 |     |         // |    1010    |   10    |        table[10] = 3        |
 641 |     |         // |    1011    |   11    |        table[11] = 3        |
 642 |     |         // |    1100    |   12    |        table[12] = 3        |
 643 |     |         // |    1101    |   13    |        table[13] = 3        |
 644 |     |         // |    1110    |   14    |        table[14] = 3        |
 645 |     |         // |    1111    |   15    |        table[15] = 3        |
 646 |     |         //
 647 |     |         // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
 648 |     |         assembly ("memory-safe") {
 649 |     |             r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
 650 |     |         }
 651 |     |     }
 652 |     | 
 653 |     |     /**
 654 |     |      * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
 655 |     |      * Returns 0 if given 0.
 656 |     |      */
 657 |     |     function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
 658 |     |         unchecked {
 659 |     |             uint256 result = log2(value);
 660 |     |             return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
 661 |     |         }
 662 |     |     }
 663 |     | 
 664 |     |     /**
 665 |     |      * @dev Return the log in base 10 of a positive value rounded towards zero.
 666 |     |      * Returns 0 if given 0.
 667 |     |      */
 668 |     |     function log10(uint256 value) internal pure returns (uint256) {
 669 |     |         uint256 result = 0;
 670 |     |         unchecked {
 671 |     |             if (value >= 10 ** 64) {
 672 |     |                 value /= 10 ** 64;
 673 |     |                 result += 64;
 674 |     |             }
 675 |     |             if (value >= 10 ** 32) {
 676 |     |                 value /= 10 ** 32;
 677 |     |                 result += 32;
 678 |     |             }
 679 |     |             if (value >= 10 ** 16) {
 680 |     |                 value /= 10 ** 16;
 681 |     |                 result += 16;
 682 |     |             }
 683 |     |             if (value >= 10 ** 8) {
 684 |     |                 value /= 10 ** 8;
 685 |     |                 result += 8;
 686 |     |             }
 687 |     |             if (value >= 10 ** 4) {
 688 |     |                 value /= 10 ** 4;
 689 |     |                 result += 4;
 690 |     |             }
 691 |     |             if (value >= 10 ** 2) {
 692 |     |                 value /= 10 ** 2;
 693 |     |                 result += 2;
 694 |     |             }
 695 |     |             if (value >= 10 ** 1) {
 696 |     |                 result += 1;
 697 |     |             }
 698 |     |         }
 699 |     |         return result;
 700 |     |     }
 701 |     | 
 702 |     |     /**
 703 |     |      * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
 704 |     |      * Returns 0 if given 0.
 705 |     |      */
 706 |     |     function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
 707 |     |         unchecked {
 708 |     |             uint256 result = log10(value);
 709 |     |             return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
 710 |     |         }
 711 |     |     }
 712 |     | 
 713 |     |     /**
 714 |     |      * @dev Return the log in base 256 of a positive value rounded towards zero.
 715 |     |      * Returns 0 if given 0.
 716 |     |      *
 717 |     |      * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
 718 |     |      */
 719 |     |     function log256(uint256 x) internal pure returns (uint256 r) {
 720 |     |         // If value has upper 128 bits set, log2 result is at least 128
 721 |     |         r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
 722 |     |         // If upper 64 bits of 128-bit half set, add 64 to result
 723 |     |         r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
 724 |     |         // If upper 32 bits of 64-bit half set, add 32 to result
 725 |     |         r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
 726 |     |         // If upper 16 bits of 32-bit half set, add 16 to result
 727 |     |         r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
 728 |     |         // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
 729 |     |         return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
 730 |     |     }
 731 |     | 
 732 |     |     /**
 733 |     |      * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
 734 |     |      * Returns 0 if given 0.
 735 |     |      */
 736 |     |     function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
 737 |     |         unchecked {
 738 |     |             uint256 result = log256(value);
 739 |     |             return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
 740 |     |         }
 741 |     |     }
 742 |     | 
 743 |     |     /**
 744 |     |      * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
 745 |     |      */
 746 | *   |     function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
 747 | *   |         return uint8(rounding) % 2 == 1;
 748 |     |     }
 749 |     | }
 750 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol
    1 |     | // SPDX-License-Identifier: MIT
    2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
    3 |     | // This file was procedurally generated from scripts/generate/templates/SafeCast.js.
    4 |     | 
    5 |     | pragma solidity ^0.8.20;
    6 |     | 
    7 |     | /**
    8 |     |  * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
    9 |     |  * checks.
   10 |     |  *
   11 |     |  * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
   12 |     |  * easily result in undesired exploitation or bugs, since developers usually
   13 |     |  * assume that overflows raise errors. `SafeCast` restores this intuition by
   14 |     |  * reverting the transaction when such an operation overflows.
   15 |     |  *
   16 |     |  * Using this library instead of the unchecked operations eliminates an entire
   17 |     |  * class of bugs, so it's recommended to use it always.
   18 |     |  */
   19 |     | library SafeCast {
   20 |     |     /**
   21 |     |      * @dev Value doesn't fit in an uint of `bits` size.
   22 |     |      */
   23 |     |     error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
   24 |     | 
   25 |     |     /**
   26 |     |      * @dev An int value doesn't fit in an uint of `bits` size.
   27 |     |      */
   28 |     |     error SafeCastOverflowedIntToUint(int256 value);
   29 |     | 
   30 |     |     /**
   31 |     |      * @dev Value doesn't fit in an int of `bits` size.
   32 |     |      */
   33 |     |     error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
   34 |     | 
   35 |     |     /**
   36 |     |      * @dev An uint value doesn't fit in an int of `bits` size.
   37 |     |      */
   38 |     |     error SafeCastOverflowedUintToInt(uint256 value);
   39 |     | 
   40 |     |     /**
   41 |     |      * @dev Returns the downcasted uint248 from uint256, reverting on
   42 |     |      * overflow (when the input is greater than largest uint248).
   43 |     |      *
   44 |     |      * Counterpart to Solidity's `uint248` operator.
   45 |     |      *
   46 |     |      * Requirements:
   47 |     |      *
   48 |     |      * - input must fit into 248 bits
   49 |     |      */
   50 |     |     function toUint248(uint256 value) internal pure returns (uint248) {
   51 |     |         if (value > type(uint248).max) {
   52 |     |             revert SafeCastOverflowedUintDowncast(248, value);
   53 |     |         }
   54 |     |         return uint248(value);
   55 |     |     }
   56 |     | 
   57 |     |     /**
   58 |     |      * @dev Returns the downcasted uint240 from uint256, reverting on
   59 |     |      * overflow (when the input is greater than largest uint240).
   60 |     |      *
   61 |     |      * Counterpart to Solidity's `uint240` operator.
   62 |     |      *
   63 |     |      * Requirements:
   64 |     |      *
   65 |     |      * - input must fit into 240 bits
   66 |     |      */
   67 |     |     function toUint240(uint256 value) internal pure returns (uint240) {
   68 |     |         if (value > type(uint240).max) {
   69 |     |             revert SafeCastOverflowedUintDowncast(240, value);
   70 |     |         }
   71 |     |         return uint240(value);
   72 |     |     }
   73 |     | 
   74 |     |     /**
   75 |     |      * @dev Returns the downcasted uint232 from uint256, reverting on
   76 |     |      * overflow (when the input is greater than largest uint232).
   77 |     |      *
   78 |     |      * Counterpart to Solidity's `uint232` operator.
   79 |     |      *
   80 |     |      * Requirements:
   81 |     |      *
   82 |     |      * - input must fit into 232 bits
   83 |     |      */
   84 |     |     function toUint232(uint256 value) internal pure returns (uint232) {
   85 |     |         if (value > type(uint232).max) {
   86 |     |             revert SafeCastOverflowedUintDowncast(232, value);
   87 |     |         }
   88 |     |         return uint232(value);
   89 |     |     }
   90 |     | 
   91 |     |     /**
   92 |     |      * @dev Returns the downcasted uint224 from uint256, reverting on
   93 |     |      * overflow (when the input is greater than largest uint224).
   94 |     |      *
   95 |     |      * Counterpart to Solidity's `uint224` operator.
   96 |     |      *
   97 |     |      * Requirements:
   98 |     |      *
   99 |     |      * - input must fit into 224 bits
  100 |     |      */
  101 |     |     function toUint224(uint256 value) internal pure returns (uint224) {
  102 |     |         if (value > type(uint224).max) {
  103 |     |             revert SafeCastOverflowedUintDowncast(224, value);
  104 |     |         }
  105 |     |         return uint224(value);
  106 |     |     }
  107 |     | 
  108 |     |     /**
  109 |     |      * @dev Returns the downcasted uint216 from uint256, reverting on
  110 |     |      * overflow (when the input is greater than largest uint216).
  111 |     |      *
  112 |     |      * Counterpart to Solidity's `uint216` operator.
  113 |     |      *
  114 |     |      * Requirements:
  115 |     |      *
  116 |     |      * - input must fit into 216 bits
  117 |     |      */
  118 |     |     function toUint216(uint256 value) internal pure returns (uint216) {
  119 |     |         if (value > type(uint216).max) {
  120 |     |             revert SafeCastOverflowedUintDowncast(216, value);
  121 |     |         }
  122 |     |         return uint216(value);
  123 |     |     }
  124 |     | 
  125 |     |     /**
  126 |     |      * @dev Returns the downcasted uint208 from uint256, reverting on
  127 |     |      * overflow (when the input is greater than largest uint208).
  128 |     |      *
  129 |     |      * Counterpart to Solidity's `uint208` operator.
  130 |     |      *
  131 |     |      * Requirements:
  132 |     |      *
  133 |     |      * - input must fit into 208 bits
  134 |     |      */
  135 |     |     function toUint208(uint256 value) internal pure returns (uint208) {
  136 |     |         if (value > type(uint208).max) {
  137 |     |             revert SafeCastOverflowedUintDowncast(208, value);
  138 |     |         }
  139 |     |         return uint208(value);
  140 |     |     }
  141 |     | 
  142 |     |     /**
  143 |     |      * @dev Returns the downcasted uint200 from uint256, reverting on
  144 |     |      * overflow (when the input is greater than largest uint200).
  145 |     |      *
  146 |     |      * Counterpart to Solidity's `uint200` operator.
  147 |     |      *
  148 |     |      * Requirements:
  149 |     |      *
  150 |     |      * - input must fit into 200 bits
  151 |     |      */
  152 |     |     function toUint200(uint256 value) internal pure returns (uint200) {
  153 |     |         if (value > type(uint200).max) {
  154 |     |             revert SafeCastOverflowedUintDowncast(200, value);
  155 |     |         }
  156 |     |         return uint200(value);
  157 |     |     }
  158 |     | 
  159 |     |     /**
  160 |     |      * @dev Returns the downcasted uint192 from uint256, reverting on
  161 |     |      * overflow (when the input is greater than largest uint192).
  162 |     |      *
  163 |     |      * Counterpart to Solidity's `uint192` operator.
  164 |     |      *
  165 |     |      * Requirements:
  166 |     |      *
  167 |     |      * - input must fit into 192 bits
  168 |     |      */
  169 |     |     function toUint192(uint256 value) internal pure returns (uint192) {
  170 |     |         if (value > type(uint192).max) {
  171 |     |             revert SafeCastOverflowedUintDowncast(192, value);
  172 |     |         }
  173 |     |         return uint192(value);
  174 |     |     }
  175 |     | 
  176 |     |     /**
  177 |     |      * @dev Returns the downcasted uint184 from uint256, reverting on
  178 |     |      * overflow (when the input is greater than largest uint184).
  179 |     |      *
  180 |     |      * Counterpart to Solidity's `uint184` operator.
  181 |     |      *
  182 |     |      * Requirements:
  183 |     |      *
  184 |     |      * - input must fit into 184 bits
  185 |     |      */
  186 |     |     function toUint184(uint256 value) internal pure returns (uint184) {
  187 |     |         if (value > type(uint184).max) {
  188 |     |             revert SafeCastOverflowedUintDowncast(184, value);
  189 |     |         }
  190 |     |         return uint184(value);
  191 |     |     }
  192 |     | 
  193 |     |     /**
  194 |     |      * @dev Returns the downcasted uint176 from uint256, reverting on
  195 |     |      * overflow (when the input is greater than largest uint176).
  196 |     |      *
  197 |     |      * Counterpart to Solidity's `uint176` operator.
  198 |     |      *
  199 |     |      * Requirements:
  200 |     |      *
  201 |     |      * - input must fit into 176 bits
  202 |     |      */
  203 |     |     function toUint176(uint256 value) internal pure returns (uint176) {
  204 |     |         if (value > type(uint176).max) {
  205 |     |             revert SafeCastOverflowedUintDowncast(176, value);
  206 |     |         }
  207 |     |         return uint176(value);
  208 |     |     }
  209 |     | 
  210 |     |     /**
  211 |     |      * @dev Returns the downcasted uint168 from uint256, reverting on
  212 |     |      * overflow (when the input is greater than largest uint168).
  213 |     |      *
  214 |     |      * Counterpart to Solidity's `uint168` operator.
  215 |     |      *
  216 |     |      * Requirements:
  217 |     |      *
  218 |     |      * - input must fit into 168 bits
  219 |     |      */
  220 |     |     function toUint168(uint256 value) internal pure returns (uint168) {
  221 |     |         if (value > type(uint168).max) {
  222 |     |             revert SafeCastOverflowedUintDowncast(168, value);
  223 |     |         }
  224 |     |         return uint168(value);
  225 |     |     }
  226 |     | 
  227 |     |     /**
  228 |     |      * @dev Returns the downcasted uint160 from uint256, reverting on
  229 |     |      * overflow (when the input is greater than largest uint160).
  230 |     |      *
  231 |     |      * Counterpart to Solidity's `uint160` operator.
  232 |     |      *
  233 |     |      * Requirements:
  234 |     |      *
  235 |     |      * - input must fit into 160 bits
  236 |     |      */
  237 |     |     function toUint160(uint256 value) internal pure returns (uint160) {
  238 |     |         if (value > type(uint160).max) {
  239 |     |             revert SafeCastOverflowedUintDowncast(160, value);
  240 |     |         }
  241 |     |         return uint160(value);
  242 |     |     }
  243 |     | 
  244 |     |     /**
  245 |     |      * @dev Returns the downcasted uint152 from uint256, reverting on
  246 |     |      * overflow (when the input is greater than largest uint152).
  247 |     |      *
  248 |     |      * Counterpart to Solidity's `uint152` operator.
  249 |     |      *
  250 |     |      * Requirements:
  251 |     |      *
  252 |     |      * - input must fit into 152 bits
  253 |     |      */
  254 |     |     function toUint152(uint256 value) internal pure returns (uint152) {
  255 |     |         if (value > type(uint152).max) {
  256 |     |             revert SafeCastOverflowedUintDowncast(152, value);
  257 |     |         }
  258 |     |         return uint152(value);
  259 |     |     }
  260 |     | 
  261 |     |     /**
  262 |     |      * @dev Returns the downcasted uint144 from uint256, reverting on
  263 |     |      * overflow (when the input is greater than largest uint144).
  264 |     |      *
  265 |     |      * Counterpart to Solidity's `uint144` operator.
  266 |     |      *
  267 |     |      * Requirements:
  268 |     |      *
  269 |     |      * - input must fit into 144 bits
  270 |     |      */
  271 |     |     function toUint144(uint256 value) internal pure returns (uint144) {
  272 |     |         if (value > type(uint144).max) {
  273 |     |             revert SafeCastOverflowedUintDowncast(144, value);
  274 |     |         }
  275 |     |         return uint144(value);
  276 |     |     }
  277 |     | 
  278 |     |     /**
  279 |     |      * @dev Returns the downcasted uint136 from uint256, reverting on
  280 |     |      * overflow (when the input is greater than largest uint136).
  281 |     |      *
  282 |     |      * Counterpart to Solidity's `uint136` operator.
  283 |     |      *
  284 |     |      * Requirements:
  285 |     |      *
  286 |     |      * - input must fit into 136 bits
  287 |     |      */
  288 |     |     function toUint136(uint256 value) internal pure returns (uint136) {
  289 |     |         if (value > type(uint136).max) {
  290 |     |             revert SafeCastOverflowedUintDowncast(136, value);
  291 |     |         }
  292 |     |         return uint136(value);
  293 |     |     }
  294 |     | 
  295 |     |     /**
  296 |     |      * @dev Returns the downcasted uint128 from uint256, reverting on
  297 |     |      * overflow (when the input is greater than largest uint128).
  298 |     |      *
  299 |     |      * Counterpart to Solidity's `uint128` operator.
  300 |     |      *
  301 |     |      * Requirements:
  302 |     |      *
  303 |     |      * - input must fit into 128 bits
  304 |     |      */
  305 |     |     function toUint128(uint256 value) internal pure returns (uint128) {
  306 |     |         if (value > type(uint128).max) {
  307 |     |             revert SafeCastOverflowedUintDowncast(128, value);
  308 |     |         }
  309 |     |         return uint128(value);
  310 |     |     }
  311 |     | 
  312 |     |     /**
  313 |     |      * @dev Returns the downcasted uint120 from uint256, reverting on
  314 |     |      * overflow (when the input is greater than largest uint120).
  315 |     |      *
  316 |     |      * Counterpart to Solidity's `uint120` operator.
  317 |     |      *
  318 |     |      * Requirements:
  319 |     |      *
  320 |     |      * - input must fit into 120 bits
  321 |     |      */
  322 |     |     function toUint120(uint256 value) internal pure returns (uint120) {
  323 |     |         if (value > type(uint120).max) {
  324 |     |             revert SafeCastOverflowedUintDowncast(120, value);
  325 |     |         }
  326 |     |         return uint120(value);
  327 |     |     }
  328 |     | 
  329 |     |     /**
  330 |     |      * @dev Returns the downcasted uint112 from uint256, reverting on
  331 |     |      * overflow (when the input is greater than largest uint112).
  332 |     |      *
  333 |     |      * Counterpart to Solidity's `uint112` operator.
  334 |     |      *
  335 |     |      * Requirements:
  336 |     |      *
  337 |     |      * - input must fit into 112 bits
  338 |     |      */
  339 |     |     function toUint112(uint256 value) internal pure returns (uint112) {
  340 |     |         if (value > type(uint112).max) {
  341 |     |             revert SafeCastOverflowedUintDowncast(112, value);
  342 |     |         }
  343 |     |         return uint112(value);
  344 |     |     }
  345 |     | 
  346 |     |     /**
  347 |     |      * @dev Returns the downcasted uint104 from uint256, reverting on
  348 |     |      * overflow (when the input is greater than largest uint104).
  349 |     |      *
  350 |     |      * Counterpart to Solidity's `uint104` operator.
  351 |     |      *
  352 |     |      * Requirements:
  353 |     |      *
  354 |     |      * - input must fit into 104 bits
  355 |     |      */
  356 |     |     function toUint104(uint256 value) internal pure returns (uint104) {
  357 |     |         if (value > type(uint104).max) {
  358 |     |             revert SafeCastOverflowedUintDowncast(104, value);
  359 |     |         }
  360 |     |         return uint104(value);
  361 |     |     }
  362 |     | 
  363 |     |     /**
  364 |     |      * @dev Returns the downcasted uint96 from uint256, reverting on
  365 |     |      * overflow (when the input is greater than largest uint96).
  366 |     |      *
  367 |     |      * Counterpart to Solidity's `uint96` operator.
  368 |     |      *
  369 |     |      * Requirements:
  370 |     |      *
  371 |     |      * - input must fit into 96 bits
  372 |     |      */
  373 |     |     function toUint96(uint256 value) internal pure returns (uint96) {
  374 |     |         if (value > type(uint96).max) {
  375 |     |             revert SafeCastOverflowedUintDowncast(96, value);
  376 |     |         }
  377 |     |         return uint96(value);
  378 |     |     }
  379 |     | 
  380 |     |     /**
  381 |     |      * @dev Returns the downcasted uint88 from uint256, reverting on
  382 |     |      * overflow (when the input is greater than largest uint88).
  383 |     |      *
  384 |     |      * Counterpart to Solidity's `uint88` operator.
  385 |     |      *
  386 |     |      * Requirements:
  387 |     |      *
  388 |     |      * - input must fit into 88 bits
  389 |     |      */
  390 |     |     function toUint88(uint256 value) internal pure returns (uint88) {
  391 |     |         if (value > type(uint88).max) {
  392 |     |             revert SafeCastOverflowedUintDowncast(88, value);
  393 |     |         }
  394 |     |         return uint88(value);
  395 |     |     }
  396 |     | 
  397 |     |     /**
  398 |     |      * @dev Returns the downcasted uint80 from uint256, reverting on
  399 |     |      * overflow (when the input is greater than largest uint80).
  400 |     |      *
  401 |     |      * Counterpart to Solidity's `uint80` operator.
  402 |     |      *
  403 |     |      * Requirements:
  404 |     |      *
  405 |     |      * - input must fit into 80 bits
  406 |     |      */
  407 |     |     function toUint80(uint256 value) internal pure returns (uint80) {
  408 |     |         if (value > type(uint80).max) {
  409 |     |             revert SafeCastOverflowedUintDowncast(80, value);
  410 |     |         }
  411 |     |         return uint80(value);
  412 |     |     }
  413 |     | 
  414 |     |     /**
  415 |     |      * @dev Returns the downcasted uint72 from uint256, reverting on
  416 |     |      * overflow (when the input is greater than largest uint72).
  417 |     |      *
  418 |     |      * Counterpart to Solidity's `uint72` operator.
  419 |     |      *
  420 |     |      * Requirements:
  421 |     |      *
  422 |     |      * - input must fit into 72 bits
  423 |     |      */
  424 |     |     function toUint72(uint256 value) internal pure returns (uint72) {
  425 |     |         if (value > type(uint72).max) {
  426 |     |             revert SafeCastOverflowedUintDowncast(72, value);
  427 |     |         }
  428 |     |         return uint72(value);
  429 |     |     }
  430 |     | 
  431 |     |     /**
  432 |     |      * @dev Returns the downcasted uint64 from uint256, reverting on
  433 |     |      * overflow (when the input is greater than largest uint64).
  434 |     |      *
  435 |     |      * Counterpart to Solidity's `uint64` operator.
  436 |     |      *
  437 |     |      * Requirements:
  438 |     |      *
  439 |     |      * - input must fit into 64 bits
  440 |     |      */
  441 |     |     function toUint64(uint256 value) internal pure returns (uint64) {
  442 |     |         if (value > type(uint64).max) {
  443 |     |             revert SafeCastOverflowedUintDowncast(64, value);
  444 |     |         }
  445 |     |         return uint64(value);
  446 |     |     }
  447 |     | 
  448 |     |     /**
  449 |     |      * @dev Returns the downcasted uint56 from uint256, reverting on
  450 |     |      * overflow (when the input is greater than largest uint56).
  451 |     |      *
  452 |     |      * Counterpart to Solidity's `uint56` operator.
  453 |     |      *
  454 |     |      * Requirements:
  455 |     |      *
  456 |     |      * - input must fit into 56 bits
  457 |     |      */
  458 |     |     function toUint56(uint256 value) internal pure returns (uint56) {
  459 |     |         if (value > type(uint56).max) {
  460 |     |             revert SafeCastOverflowedUintDowncast(56, value);
  461 |     |         }
  462 |     |         return uint56(value);
  463 |     |     }
  464 |     | 
  465 |     |     /**
  466 |     |      * @dev Returns the downcasted uint48 from uint256, reverting on
  467 |     |      * overflow (when the input is greater than largest uint48).
  468 |     |      *
  469 |     |      * Counterpart to Solidity's `uint48` operator.
  470 |     |      *
  471 |     |      * Requirements:
  472 |     |      *
  473 |     |      * - input must fit into 48 bits
  474 |     |      */
  475 |     |     function toUint48(uint256 value) internal pure returns (uint48) {
  476 |     |         if (value > type(uint48).max) {
  477 |     |             revert SafeCastOverflowedUintDowncast(48, value);
  478 |     |         }
  479 |     |         return uint48(value);
  480 |     |     }
  481 |     | 
  482 |     |     /**
  483 |     |      * @dev Returns the downcasted uint40 from uint256, reverting on
  484 |     |      * overflow (when the input is greater than largest uint40).
  485 |     |      *
  486 |     |      * Counterpart to Solidity's `uint40` operator.
  487 |     |      *
  488 |     |      * Requirements:
  489 |     |      *
  490 |     |      * - input must fit into 40 bits
  491 |     |      */
  492 |     |     function toUint40(uint256 value) internal pure returns (uint40) {
  493 |     |         if (value > type(uint40).max) {
  494 |     |             revert SafeCastOverflowedUintDowncast(40, value);
  495 |     |         }
  496 |     |         return uint40(value);
  497 |     |     }
  498 |     | 
  499 |     |     /**
  500 |     |      * @dev Returns the downcasted uint32 from uint256, reverting on
  501 |     |      * overflow (when the input is greater than largest uint32).
  502 |     |      *
  503 |     |      * Counterpart to Solidity's `uint32` operator.
  504 |     |      *
  505 |     |      * Requirements:
  506 |     |      *
  507 |     |      * - input must fit into 32 bits
  508 |     |      */
  509 |     |     function toUint32(uint256 value) internal pure returns (uint32) {
  510 |     |         if (value > type(uint32).max) {
  511 |     |             revert SafeCastOverflowedUintDowncast(32, value);
  512 |     |         }
  513 |     |         return uint32(value);
  514 |     |     }
  515 |     | 
  516 |     |     /**
  517 |     |      * @dev Returns the downcasted uint24 from uint256, reverting on
  518 |     |      * overflow (when the input is greater than largest uint24).
  519 |     |      *
  520 |     |      * Counterpart to Solidity's `uint24` operator.
  521 |     |      *
  522 |     |      * Requirements:
  523 |     |      *
  524 |     |      * - input must fit into 24 bits
  525 |     |      */
  526 |     |     function toUint24(uint256 value) internal pure returns (uint24) {
  527 |     |         if (value > type(uint24).max) {
  528 |     |             revert SafeCastOverflowedUintDowncast(24, value);
  529 |     |         }
  530 |     |         return uint24(value);
  531 |     |     }
  532 |     | 
  533 |     |     /**
  534 |     |      * @dev Returns the downcasted uint16 from uint256, reverting on
  535 |     |      * overflow (when the input is greater than largest uint16).
  536 |     |      *
  537 |     |      * Counterpart to Solidity's `uint16` operator.
  538 |     |      *
  539 |     |      * Requirements:
  540 |     |      *
  541 |     |      * - input must fit into 16 bits
  542 |     |      */
  543 |     |     function toUint16(uint256 value) internal pure returns (uint16) {
  544 |     |         if (value > type(uint16).max) {
  545 |     |             revert SafeCastOverflowedUintDowncast(16, value);
  546 |     |         }
  547 |     |         return uint16(value);
  548 |     |     }
  549 |     | 
  550 |     |     /**
  551 |     |      * @dev Returns the downcasted uint8 from uint256, reverting on
  552 |     |      * overflow (when the input is greater than largest uint8).
  553 |     |      *
  554 |     |      * Counterpart to Solidity's `uint8` operator.
  555 |     |      *
  556 |     |      * Requirements:
  557 |     |      *
  558 |     |      * - input must fit into 8 bits
  559 |     |      */
  560 |     |     function toUint8(uint256 value) internal pure returns (uint8) {
  561 |     |         if (value > type(uint8).max) {
  562 |     |             revert SafeCastOverflowedUintDowncast(8, value);
  563 |     |         }
  564 |     |         return uint8(value);
  565 |     |     }
  566 |     | 
  567 |     |     /**
  568 |     |      * @dev Converts a signed int256 into an unsigned uint256.
  569 |     |      *
  570 |     |      * Requirements:
  571 |     |      *
  572 |     |      * - input must be greater than or equal to 0.
  573 |     |      */
  574 |     |     function toUint256(int256 value) internal pure returns (uint256) {
  575 |     |         if (value < 0) {
  576 |     |             revert SafeCastOverflowedIntToUint(value);
  577 |     |         }
  578 |     |         return uint256(value);
  579 |     |     }
  580 |     | 
  581 |     |     /**
  582 |     |      * @dev Returns the downcasted int248 from int256, reverting on
  583 |     |      * overflow (when the input is less than smallest int248 or
  584 |     |      * greater than largest int248).
  585 |     |      *
  586 |     |      * Counterpart to Solidity's `int248` operator.
  587 |     |      *
  588 |     |      * Requirements:
  589 |     |      *
  590 |     |      * - input must fit into 248 bits
  591 |     |      */
  592 |     |     function toInt248(int256 value) internal pure returns (int248 downcasted) {
  593 |     |         downcasted = int248(value);
  594 |     |         if (downcasted != value) {
  595 |     |             revert SafeCastOverflowedIntDowncast(248, value);
  596 |     |         }
  597 |     |     }
  598 |     | 
  599 |     |     /**
  600 |     |      * @dev Returns the downcasted int240 from int256, reverting on
  601 |     |      * overflow (when the input is less than smallest int240 or
  602 |     |      * greater than largest int240).
  603 |     |      *
  604 |     |      * Counterpart to Solidity's `int240` operator.
  605 |     |      *
  606 |     |      * Requirements:
  607 |     |      *
  608 |     |      * - input must fit into 240 bits
  609 |     |      */
  610 |     |     function toInt240(int256 value) internal pure returns (int240 downcasted) {
  611 |     |         downcasted = int240(value);
  612 |     |         if (downcasted != value) {
  613 |     |             revert SafeCastOverflowedIntDowncast(240, value);
  614 |     |         }
  615 |     |     }
  616 |     | 
  617 |     |     /**
  618 |     |      * @dev Returns the downcasted int232 from int256, reverting on
  619 |     |      * overflow (when the input is less than smallest int232 or
  620 |     |      * greater than largest int232).
  621 |     |      *
  622 |     |      * Counterpart to Solidity's `int232` operator.
  623 |     |      *
  624 |     |      * Requirements:
  625 |     |      *
  626 |     |      * - input must fit into 232 bits
  627 |     |      */
  628 |     |     function toInt232(int256 value) internal pure returns (int232 downcasted) {
  629 |     |         downcasted = int232(value);
  630 |     |         if (downcasted != value) {
  631 |     |             revert SafeCastOverflowedIntDowncast(232, value);
  632 |     |         }
  633 |     |     }
  634 |     | 
  635 |     |     /**
  636 |     |      * @dev Returns the downcasted int224 from int256, reverting on
  637 |     |      * overflow (when the input is less than smallest int224 or
  638 |     |      * greater than largest int224).
  639 |     |      *
  640 |     |      * Counterpart to Solidity's `int224` operator.
  641 |     |      *
  642 |     |      * Requirements:
  643 |     |      *
  644 |     |      * - input must fit into 224 bits
  645 |     |      */
  646 |     |     function toInt224(int256 value) internal pure returns (int224 downcasted) {
  647 |     |         downcasted = int224(value);
  648 |     |         if (downcasted != value) {
  649 |     |             revert SafeCastOverflowedIntDowncast(224, value);
  650 |     |         }
  651 |     |     }
  652 |     | 
  653 |     |     /**
  654 |     |      * @dev Returns the downcasted int216 from int256, reverting on
  655 |     |      * overflow (when the input is less than smallest int216 or
  656 |     |      * greater than largest int216).
  657 |     |      *
  658 |     |      * Counterpart to Solidity's `int216` operator.
  659 |     |      *
  660 |     |      * Requirements:
  661 |     |      *
  662 |     |      * - input must fit into 216 bits
  663 |     |      */
  664 |     |     function toInt216(int256 value) internal pure returns (int216 downcasted) {
  665 |     |         downcasted = int216(value);
  666 |     |         if (downcasted != value) {
  667 |     |             revert SafeCastOverflowedIntDowncast(216, value);
  668 |     |         }
  669 |     |     }
  670 |     | 
  671 |     |     /**
  672 |     |      * @dev Returns the downcasted int208 from int256, reverting on
  673 |     |      * overflow (when the input is less than smallest int208 or
  674 |     |      * greater than largest int208).
  675 |     |      *
  676 |     |      * Counterpart to Solidity's `int208` operator.
  677 |     |      *
  678 |     |      * Requirements:
  679 |     |      *
  680 |     |      * - input must fit into 208 bits
  681 |     |      */
  682 |     |     function toInt208(int256 value) internal pure returns (int208 downcasted) {
  683 |     |         downcasted = int208(value);
  684 |     |         if (downcasted != value) {
  685 |     |             revert SafeCastOverflowedIntDowncast(208, value);
  686 |     |         }
  687 |     |     }
  688 |     | 
  689 |     |     /**
  690 |     |      * @dev Returns the downcasted int200 from int256, reverting on
  691 |     |      * overflow (when the input is less than smallest int200 or
  692 |     |      * greater than largest int200).
  693 |     |      *
  694 |     |      * Counterpart to Solidity's `int200` operator.
  695 |     |      *
  696 |     |      * Requirements:
  697 |     |      *
  698 |     |      * - input must fit into 200 bits
  699 |     |      */
  700 |     |     function toInt200(int256 value) internal pure returns (int200 downcasted) {
  701 |     |         downcasted = int200(value);
  702 |     |         if (downcasted != value) {
  703 |     |             revert SafeCastOverflowedIntDowncast(200, value);
  704 |     |         }
  705 |     |     }
  706 |     | 
  707 |     |     /**
  708 |     |      * @dev Returns the downcasted int192 from int256, reverting on
  709 |     |      * overflow (when the input is less than smallest int192 or
  710 |     |      * greater than largest int192).
  711 |     |      *
  712 |     |      * Counterpart to Solidity's `int192` operator.
  713 |     |      *
  714 |     |      * Requirements:
  715 |     |      *
  716 |     |      * - input must fit into 192 bits
  717 |     |      */
  718 |     |     function toInt192(int256 value) internal pure returns (int192 downcasted) {
  719 |     |         downcasted = int192(value);
  720 |     |         if (downcasted != value) {
  721 |     |             revert SafeCastOverflowedIntDowncast(192, value);
  722 |     |         }
  723 |     |     }
  724 |     | 
  725 |     |     /**
  726 |     |      * @dev Returns the downcasted int184 from int256, reverting on
  727 |     |      * overflow (when the input is less than smallest int184 or
  728 |     |      * greater than largest int184).
  729 |     |      *
  730 |     |      * Counterpart to Solidity's `int184` operator.
  731 |     |      *
  732 |     |      * Requirements:
  733 |     |      *
  734 |     |      * - input must fit into 184 bits
  735 |     |      */
  736 |     |     function toInt184(int256 value) internal pure returns (int184 downcasted) {
  737 |     |         downcasted = int184(value);
  738 |     |         if (downcasted != value) {
  739 |     |             revert SafeCastOverflowedIntDowncast(184, value);
  740 |     |         }
  741 |     |     }
  742 |     | 
  743 |     |     /**
  744 |     |      * @dev Returns the downcasted int176 from int256, reverting on
  745 |     |      * overflow (when the input is less than smallest int176 or
  746 |     |      * greater than largest int176).
  747 |     |      *
  748 |     |      * Counterpart to Solidity's `int176` operator.
  749 |     |      *
  750 |     |      * Requirements:
  751 |     |      *
  752 |     |      * - input must fit into 176 bits
  753 |     |      */
  754 |     |     function toInt176(int256 value) internal pure returns (int176 downcasted) {
  755 |     |         downcasted = int176(value);
  756 |     |         if (downcasted != value) {
  757 |     |             revert SafeCastOverflowedIntDowncast(176, value);
  758 |     |         }
  759 |     |     }
  760 |     | 
  761 |     |     /**
  762 |     |      * @dev Returns the downcasted int168 from int256, reverting on
  763 |     |      * overflow (when the input is less than smallest int168 or
  764 |     |      * greater than largest int168).
  765 |     |      *
  766 |     |      * Counterpart to Solidity's `int168` operator.
  767 |     |      *
  768 |     |      * Requirements:
  769 |     |      *
  770 |     |      * - input must fit into 168 bits
  771 |     |      */
  772 |     |     function toInt168(int256 value) internal pure returns (int168 downcasted) {
  773 |     |         downcasted = int168(value);
  774 |     |         if (downcasted != value) {
  775 |     |             revert SafeCastOverflowedIntDowncast(168, value);
  776 |     |         }
  777 |     |     }
  778 |     | 
  779 |     |     /**
  780 |     |      * @dev Returns the downcasted int160 from int256, reverting on
  781 |     |      * overflow (when the input is less than smallest int160 or
  782 |     |      * greater than largest int160).
  783 |     |      *
  784 |     |      * Counterpart to Solidity's `int160` operator.
  785 |     |      *
  786 |     |      * Requirements:
  787 |     |      *
  788 |     |      * - input must fit into 160 bits
  789 |     |      */
  790 |     |     function toInt160(int256 value) internal pure returns (int160 downcasted) {
  791 |     |         downcasted = int160(value);
  792 |     |         if (downcasted != value) {
  793 |     |             revert SafeCastOverflowedIntDowncast(160, value);
  794 |     |         }
  795 |     |     }
  796 |     | 
  797 |     |     /**
  798 |     |      * @dev Returns the downcasted int152 from int256, reverting on
  799 |     |      * overflow (when the input is less than smallest int152 or
  800 |     |      * greater than largest int152).
  801 |     |      *
  802 |     |      * Counterpart to Solidity's `int152` operator.
  803 |     |      *
  804 |     |      * Requirements:
  805 |     |      *
  806 |     |      * - input must fit into 152 bits
  807 |     |      */
  808 |     |     function toInt152(int256 value) internal pure returns (int152 downcasted) {
  809 |     |         downcasted = int152(value);
  810 |     |         if (downcasted != value) {
  811 |     |             revert SafeCastOverflowedIntDowncast(152, value);
  812 |     |         }
  813 |     |     }
  814 |     | 
  815 |     |     /**
  816 |     |      * @dev Returns the downcasted int144 from int256, reverting on
  817 |     |      * overflow (when the input is less than smallest int144 or
  818 |     |      * greater than largest int144).
  819 |     |      *
  820 |     |      * Counterpart to Solidity's `int144` operator.
  821 |     |      *
  822 |     |      * Requirements:
  823 |     |      *
  824 |     |      * - input must fit into 144 bits
  825 |     |      */
  826 |     |     function toInt144(int256 value) internal pure returns (int144 downcasted) {
  827 |     |         downcasted = int144(value);
  828 |     |         if (downcasted != value) {
  829 |     |             revert SafeCastOverflowedIntDowncast(144, value);
  830 |     |         }
  831 |     |     }
  832 |     | 
  833 |     |     /**
  834 |     |      * @dev Returns the downcasted int136 from int256, reverting on
  835 |     |      * overflow (when the input is less than smallest int136 or
  836 |     |      * greater than largest int136).
  837 |     |      *
  838 |     |      * Counterpart to Solidity's `int136` operator.
  839 |     |      *
  840 |     |      * Requirements:
  841 |     |      *
  842 |     |      * - input must fit into 136 bits
  843 |     |      */
  844 |     |     function toInt136(int256 value) internal pure returns (int136 downcasted) {
  845 |     |         downcasted = int136(value);
  846 |     |         if (downcasted != value) {
  847 |     |             revert SafeCastOverflowedIntDowncast(136, value);
  848 |     |         }
  849 |     |     }
  850 |     | 
  851 |     |     /**
  852 |     |      * @dev Returns the downcasted int128 from int256, reverting on
  853 |     |      * overflow (when the input is less than smallest int128 or
  854 |     |      * greater than largest int128).
  855 |     |      *
  856 |     |      * Counterpart to Solidity's `int128` operator.
  857 |     |      *
  858 |     |      * Requirements:
  859 |     |      *
  860 |     |      * - input must fit into 128 bits
  861 |     |      */
  862 |     |     function toInt128(int256 value) internal pure returns (int128 downcasted) {
  863 |     |         downcasted = int128(value);
  864 |     |         if (downcasted != value) {
  865 |     |             revert SafeCastOverflowedIntDowncast(128, value);
  866 |     |         }
  867 |     |     }
  868 |     | 
  869 |     |     /**
  870 |     |      * @dev Returns the downcasted int120 from int256, reverting on
  871 |     |      * overflow (when the input is less than smallest int120 or
  872 |     |      * greater than largest int120).
  873 |     |      *
  874 |     |      * Counterpart to Solidity's `int120` operator.
  875 |     |      *
  876 |     |      * Requirements:
  877 |     |      *
  878 |     |      * - input must fit into 120 bits
  879 |     |      */
  880 |     |     function toInt120(int256 value) internal pure returns (int120 downcasted) {
  881 |     |         downcasted = int120(value);
  882 |     |         if (downcasted != value) {
  883 |     |             revert SafeCastOverflowedIntDowncast(120, value);
  884 |     |         }
  885 |     |     }
  886 |     | 
  887 |     |     /**
  888 |     |      * @dev Returns the downcasted int112 from int256, reverting on
  889 |     |      * overflow (when the input is less than smallest int112 or
  890 |     |      * greater than largest int112).
  891 |     |      *
  892 |     |      * Counterpart to Solidity's `int112` operator.
  893 |     |      *
  894 |     |      * Requirements:
  895 |     |      *
  896 |     |      * - input must fit into 112 bits
  897 |     |      */
  898 |     |     function toInt112(int256 value) internal pure returns (int112 downcasted) {
  899 |     |         downcasted = int112(value);
  900 |     |         if (downcasted != value) {
  901 |     |             revert SafeCastOverflowedIntDowncast(112, value);
  902 |     |         }
  903 |     |     }
  904 |     | 
  905 |     |     /**
  906 |     |      * @dev Returns the downcasted int104 from int256, reverting on
  907 |     |      * overflow (when the input is less than smallest int104 or
  908 |     |      * greater than largest int104).
  909 |     |      *
  910 |     |      * Counterpart to Solidity's `int104` operator.
  911 |     |      *
  912 |     |      * Requirements:
  913 |     |      *
  914 |     |      * - input must fit into 104 bits
  915 |     |      */
  916 |     |     function toInt104(int256 value) internal pure returns (int104 downcasted) {
  917 |     |         downcasted = int104(value);
  918 |     |         if (downcasted != value) {
  919 |     |             revert SafeCastOverflowedIntDowncast(104, value);
  920 |     |         }
  921 |     |     }
  922 |     | 
  923 |     |     /**
  924 |     |      * @dev Returns the downcasted int96 from int256, reverting on
  925 |     |      * overflow (when the input is less than smallest int96 or
  926 |     |      * greater than largest int96).
  927 |     |      *
  928 |     |      * Counterpart to Solidity's `int96` operator.
  929 |     |      *
  930 |     |      * Requirements:
  931 |     |      *
  932 |     |      * - input must fit into 96 bits
  933 |     |      */
  934 |     |     function toInt96(int256 value) internal pure returns (int96 downcasted) {
  935 |     |         downcasted = int96(value);
  936 |     |         if (downcasted != value) {
  937 |     |             revert SafeCastOverflowedIntDowncast(96, value);
  938 |     |         }
  939 |     |     }
  940 |     | 
  941 |     |     /**
  942 |     |      * @dev Returns the downcasted int88 from int256, reverting on
  943 |     |      * overflow (when the input is less than smallest int88 or
  944 |     |      * greater than largest int88).
  945 |     |      *
  946 |     |      * Counterpart to Solidity's `int88` operator.
  947 |     |      *
  948 |     |      * Requirements:
  949 |     |      *
  950 |     |      * - input must fit into 88 bits
  951 |     |      */
  952 |     |     function toInt88(int256 value) internal pure returns (int88 downcasted) {
  953 |     |         downcasted = int88(value);
  954 |     |         if (downcasted != value) {
  955 |     |             revert SafeCastOverflowedIntDowncast(88, value);
  956 |     |         }
  957 |     |     }
  958 |     | 
  959 |     |     /**
  960 |     |      * @dev Returns the downcasted int80 from int256, reverting on
  961 |     |      * overflow (when the input is less than smallest int80 or
  962 |     |      * greater than largest int80).
  963 |     |      *
  964 |     |      * Counterpart to Solidity's `int80` operator.
  965 |     |      *
  966 |     |      * Requirements:
  967 |     |      *
  968 |     |      * - input must fit into 80 bits
  969 |     |      */
  970 |     |     function toInt80(int256 value) internal pure returns (int80 downcasted) {
  971 |     |         downcasted = int80(value);
  972 |     |         if (downcasted != value) {
  973 |     |             revert SafeCastOverflowedIntDowncast(80, value);
  974 |     |         }
  975 |     |     }
  976 |     | 
  977 |     |     /**
  978 |     |      * @dev Returns the downcasted int72 from int256, reverting on
  979 |     |      * overflow (when the input is less than smallest int72 or
  980 |     |      * greater than largest int72).
  981 |     |      *
  982 |     |      * Counterpart to Solidity's `int72` operator.
  983 |     |      *
  984 |     |      * Requirements:
  985 |     |      *
  986 |     |      * - input must fit into 72 bits
  987 |     |      */
  988 |     |     function toInt72(int256 value) internal pure returns (int72 downcasted) {
  989 |     |         downcasted = int72(value);
  990 |     |         if (downcasted != value) {
  991 |     |             revert SafeCastOverflowedIntDowncast(72, value);
  992 |     |         }
  993 |     |     }
  994 |     | 
  995 |     |     /**
  996 |     |      * @dev Returns the downcasted int64 from int256, reverting on
  997 |     |      * overflow (when the input is less than smallest int64 or
  998 |     |      * greater than largest int64).
  999 |     |      *
 1000 |     |      * Counterpart to Solidity's `int64` operator.
 1001 |     |      *
 1002 |     |      * Requirements:
 1003 |     |      *
 1004 |     |      * - input must fit into 64 bits
 1005 |     |      */
 1006 |     |     function toInt64(int256 value) internal pure returns (int64 downcasted) {
 1007 |     |         downcasted = int64(value);
 1008 |     |         if (downcasted != value) {
 1009 |     |             revert SafeCastOverflowedIntDowncast(64, value);
 1010 |     |         }
 1011 |     |     }
 1012 |     | 
 1013 |     |     /**
 1014 |     |      * @dev Returns the downcasted int56 from int256, reverting on
 1015 |     |      * overflow (when the input is less than smallest int56 or
 1016 |     |      * greater than largest int56).
 1017 |     |      *
 1018 |     |      * Counterpart to Solidity's `int56` operator.
 1019 |     |      *
 1020 |     |      * Requirements:
 1021 |     |      *
 1022 |     |      * - input must fit into 56 bits
 1023 |     |      */
 1024 |     |     function toInt56(int256 value) internal pure returns (int56 downcasted) {
 1025 |     |         downcasted = int56(value);
 1026 |     |         if (downcasted != value) {
 1027 |     |             revert SafeCastOverflowedIntDowncast(56, value);
 1028 |     |         }
 1029 |     |     }
 1030 |     | 
 1031 |     |     /**
 1032 |     |      * @dev Returns the downcasted int48 from int256, reverting on
 1033 |     |      * overflow (when the input is less than smallest int48 or
 1034 |     |      * greater than largest int48).
 1035 |     |      *
 1036 |     |      * Counterpart to Solidity's `int48` operator.
 1037 |     |      *
 1038 |     |      * Requirements:
 1039 |     |      *
 1040 |     |      * - input must fit into 48 bits
 1041 |     |      */
 1042 |     |     function toInt48(int256 value) internal pure returns (int48 downcasted) {
 1043 |     |         downcasted = int48(value);
 1044 |     |         if (downcasted != value) {
 1045 |     |             revert SafeCastOverflowedIntDowncast(48, value);
 1046 |     |         }
 1047 |     |     }
 1048 |     | 
 1049 |     |     /**
 1050 |     |      * @dev Returns the downcasted int40 from int256, reverting on
 1051 |     |      * overflow (when the input is less than smallest int40 or
 1052 |     |      * greater than largest int40).
 1053 |     |      *
 1054 |     |      * Counterpart to Solidity's `int40` operator.
 1055 |     |      *
 1056 |     |      * Requirements:
 1057 |     |      *
 1058 |     |      * - input must fit into 40 bits
 1059 |     |      */
 1060 |     |     function toInt40(int256 value) internal pure returns (int40 downcasted) {
 1061 |     |         downcasted = int40(value);
 1062 |     |         if (downcasted != value) {
 1063 |     |             revert SafeCastOverflowedIntDowncast(40, value);
 1064 |     |         }
 1065 |     |     }
 1066 |     | 
 1067 |     |     /**
 1068 |     |      * @dev Returns the downcasted int32 from int256, reverting on
 1069 |     |      * overflow (when the input is less than smallest int32 or
 1070 |     |      * greater than largest int32).
 1071 |     |      *
 1072 |     |      * Counterpart to Solidity's `int32` operator.
 1073 |     |      *
 1074 |     |      * Requirements:
 1075 |     |      *
 1076 |     |      * - input must fit into 32 bits
 1077 |     |      */
 1078 |     |     function toInt32(int256 value) internal pure returns (int32 downcasted) {
 1079 |     |         downcasted = int32(value);
 1080 |     |         if (downcasted != value) {
 1081 |     |             revert SafeCastOverflowedIntDowncast(32, value);
 1082 |     |         }
 1083 |     |     }
 1084 |     | 
 1085 |     |     /**
 1086 |     |      * @dev Returns the downcasted int24 from int256, reverting on
 1087 |     |      * overflow (when the input is less than smallest int24 or
 1088 |     |      * greater than largest int24).
 1089 |     |      *
 1090 |     |      * Counterpart to Solidity's `int24` operator.
 1091 |     |      *
 1092 |     |      * Requirements:
 1093 |     |      *
 1094 |     |      * - input must fit into 24 bits
 1095 |     |      */
 1096 |     |     function toInt24(int256 value) internal pure returns (int24 downcasted) {
 1097 |     |         downcasted = int24(value);
 1098 |     |         if (downcasted != value) {
 1099 |     |             revert SafeCastOverflowedIntDowncast(24, value);
 1100 |     |         }
 1101 |     |     }
 1102 |     | 
 1103 |     |     /**
 1104 |     |      * @dev Returns the downcasted int16 from int256, reverting on
 1105 |     |      * overflow (when the input is less than smallest int16 or
 1106 |     |      * greater than largest int16).
 1107 |     |      *
 1108 |     |      * Counterpart to Solidity's `int16` operator.
 1109 |     |      *
 1110 |     |      * Requirements:
 1111 |     |      *
 1112 |     |      * - input must fit into 16 bits
 1113 |     |      */
 1114 |     |     function toInt16(int256 value) internal pure returns (int16 downcasted) {
 1115 |     |         downcasted = int16(value);
 1116 |     |         if (downcasted != value) {
 1117 |     |             revert SafeCastOverflowedIntDowncast(16, value);
 1118 |     |         }
 1119 |     |     }
 1120 |     | 
 1121 |     |     /**
 1122 |     |      * @dev Returns the downcasted int8 from int256, reverting on
 1123 |     |      * overflow (when the input is less than smallest int8 or
 1124 |     |      * greater than largest int8).
 1125 |     |      *
 1126 |     |      * Counterpart to Solidity's `int8` operator.
 1127 |     |      *
 1128 |     |      * Requirements:
 1129 |     |      *
 1130 |     |      * - input must fit into 8 bits
 1131 |     |      */
 1132 |     |     function toInt8(int256 value) internal pure returns (int8 downcasted) {
 1133 |     |         downcasted = int8(value);
 1134 |     |         if (downcasted != value) {
 1135 |     |             revert SafeCastOverflowedIntDowncast(8, value);
 1136 |     |         }
 1137 |     |     }
 1138 |     | 
 1139 |     |     /**
 1140 |     |      * @dev Converts an unsigned uint256 into a signed int256.
 1141 |     |      *
 1142 |     |      * Requirements:
 1143 |     |      *
 1144 |     |      * - input must be less than or equal to maxInt256.
 1145 |     |      */
 1146 |     |     function toInt256(uint256 value) internal pure returns (int256) {
 1147 |     |         // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
 1148 |     |         if (value > uint256(type(int256).max)) {
 1149 |     |             revert SafeCastOverflowedUintToInt(value);
 1150 |     |         }
 1151 |     |         return int256(value);
 1152 |     |     }
 1153 |     | 
 1154 |     |     /**
 1155 |     |      * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
 1156 |     |      */
 1157 | *   |     function toUint(bool b) internal pure returns (uint256 u) {
 1158 |     |         assembly ("memory-safe") {
 1159 | *   |             u := iszero(iszero(b))
 1160 |     |         }
 1161 |     |     }
 1162 |     | }
 1163 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol
  1 |     | // SPDX-License-Identifier: MIT
  2 |     | // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)
  3 |     | 
  4 |     | pragma solidity ^0.8.20;
  5 |     | 
  6 |     | import {SafeCast} from "./SafeCast.sol";
  7 |     | 
  8 |     | /**
  9 |     |  * @dev Standard signed math utilities missing in the Solidity language.
 10 |     |  */
 11 |     | library SignedMath {
 12 |     |     /**
 13 |     |      * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
 14 |     |      *
 15 |     |      * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
 16 |     |      * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
 17 |     |      * one branch when needed, making this function more expensive.
 18 |     |      */
 19 |     |     function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
 20 |     |         unchecked {
 21 |     |             // branchless ternary works because:
 22 |     |             // b ^ (a ^ b) == a
 23 |     |             // b ^ 0 == b
 24 |     |             return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
 25 |     |         }
 26 |     |     }
 27 |     | 
 28 |     |     /**
 29 |     |      * @dev Returns the largest of two signed numbers.
 30 |     |      */
 31 |     |     function max(int256 a, int256 b) internal pure returns (int256) {
 32 |     |         return ternary(a > b, a, b);
 33 |     |     }
 34 |     | 
 35 |     |     /**
 36 |     |      * @dev Returns the smallest of two signed numbers.
 37 |     |      */
 38 |     |     function min(int256 a, int256 b) internal pure returns (int256) {
 39 |     |         return ternary(a < b, a, b);
 40 |     |     }
 41 |     | 
 42 |     |     /**
 43 |     |      * @dev Returns the average of two signed numbers without overflow.
 44 |     |      * The result is rounded towards zero.
 45 |     |      */
 46 |     |     function average(int256 a, int256 b) internal pure returns (int256) {
 47 |     |         // Formula from the book "Hacker's Delight"
 48 |     |         int256 x = (a & b) + ((a ^ b) >> 1);
 49 |     |         return x + (int256(uint256(x) >> 255) & (a ^ b));
 50 |     |     }
 51 |     | 
 52 |     |     /**
 53 |     |      * @dev Returns the absolute unsigned value of a signed value.
 54 |     |      */
 55 |     |     function abs(int256 n) internal pure returns (uint256) {
 56 |     |         unchecked {
 57 |     |             // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
 58 |     |             // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
 59 |     |             // taking advantage of the most significant (or "sign" bit) in two's complement representation.
 60 |     |             // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
 61 |     |             // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
 62 |     |             int256 mask = n >> 255;
 63 |     | 
 64 |     |             // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
 65 |     |             return uint256((n + mask) ^ mask);
 66 |     |         }
 67 |     |     }
 68 |     | }
 69 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/EnumerableSet.sol)
   3 |     | // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
   4 |     | 
   5 |     | pragma solidity ^0.8.20;
   6 |     | 
   7 |     | import {Arrays} from "../Arrays.sol";
   8 |     | import {Math} from "../math/Math.sol";
   9 |     | 
  10 |     | /**
  11 |     |  * @dev Library for managing
  12 |     |  * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
  13 |     |  * types.
  14 |     |  *
  15 |     |  * Sets have the following properties:
  16 |     |  *
  17 |     |  * - Elements are added, removed, and checked for existence in constant time
  18 |     |  * (O(1)).
  19 |     |  * - Elements are enumerated in O(n). No guarantees are made on the ordering.
  20 |     |  * - Set can be cleared (all elements removed) in O(n).
  21 |     |  *
  22 |     |  * ```solidity
  23 |     |  * contract Example {
  24 |     |  *     // Add the library methods
  25 |     |  *     using EnumerableSet for EnumerableSet.AddressSet;
  26 |     |  *
  27 |     |  *     // Declare a set state variable
  28 |     |  *     EnumerableSet.AddressSet private mySet;
  29 |     |  * }
  30 |     |  * ```
  31 |     |  *
  32 |     |  * The following types are supported:
  33 |     |  *
  34 |     |  * - `bytes32` (`Bytes32Set`) since v3.3.0
  35 |     |  * - `address` (`AddressSet`) since v3.3.0
  36 |     |  * - `uint256` (`UintSet`) since v3.3.0
  37 |     |  * - `string` (`StringSet`) since v5.4.0
  38 |     |  * - `bytes` (`BytesSet`) since v5.4.0
  39 |     |  *
  40 |     |  * [WARNING]
  41 |     |  * ====
  42 |     |  * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
  43 |     |  * unusable.
  44 |     |  * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
  45 |     |  *
  46 |     |  * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
  47 |     |  * array of EnumerableSet.
  48 |     |  * ====
  49 |     |  */
  50 |     | library EnumerableSet {
  51 |     |     // To implement this library for multiple types with as little code
  52 |     |     // repetition as possible, we write it in terms of a generic Set type with
  53 |     |     // bytes32 values.
  54 |     |     // The Set implementation uses private functions, and user-facing
  55 |     |     // implementations (such as AddressSet) are just wrappers around the
  56 |     |     // underlying Set.
  57 |     |     // This means that we can only create new EnumerableSets for types that fit
  58 |     |     // in bytes32.
  59 |     | 
  60 |     |     struct Set {
  61 |     |         // Storage of set values
  62 |     |         bytes32[] _values;
  63 |     |         // Position is the index of the value in the `values` array plus 1.
  64 |     |         // Position 0 is used to mean a value is not in the set.
  65 |     |         mapping(bytes32 value => uint256) _positions;
  66 |     |     }
  67 |     | 
  68 |     |     /**
  69 |     |      * @dev Add a value to a set. O(1).
  70 |     |      *
  71 |     |      * Returns true if the value was added to the set, that is if it was not
  72 |     |      * already present.
  73 |     |      */
  74 | *   |     function _add(Set storage set, bytes32 value) private returns (bool) {
  75 | *   |         if (!_contains(set, value)) {
  76 | *   |             set._values.push(value);
  77 |     |             // The value is stored at length-1, but we add 1 to all indexes
  78 |     |             // and use 0 as a sentinel value
  79 | *   |             set._positions[value] = set._values.length;
  80 | *   |             return true;
  81 |     |         } else {
  82 | *   |             return false;
  83 |     |         }
  84 |     |     }
  85 |     | 
  86 |     |     /**
  87 |     |      * @dev Removes a value from a set. O(1).
  88 |     |      *
  89 |     |      * Returns true if the value was removed from the set, that is if it was
  90 |     |      * present.
  91 |     |      */
  92 | *   |     function _remove(Set storage set, bytes32 value) private returns (bool) {
  93 |     |         // We cache the value's position to prevent multiple reads from the same storage slot
  94 | *   |         uint256 position = set._positions[value];
  95 |     | 
  96 | *   |         if (position != 0) {
  97 |     |             // Equivalent to contains(set, value)
  98 |     |             // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
  99 |     |             // the array, and then remove the last element (sometimes called as 'swap and pop').
 100 |     |             // This modifies the order of the array, as noted in {at}.
 101 |     | 
 102 | *   |             uint256 valueIndex = position - 1;
 103 | *   |             uint256 lastIndex = set._values.length - 1;
 104 |     | 
 105 | *   |             if (valueIndex != lastIndex) {
 106 | *   |                 bytes32 lastValue = set._values[lastIndex];
 107 |     | 
 108 |     |                 // Move the lastValue to the index where the value to delete is
 109 | *   |                 set._values[valueIndex] = lastValue;
 110 |     |                 // Update the tracked position of the lastValue (that was just moved)
 111 | *   |                 set._positions[lastValue] = position;
 112 |     |             }
 113 |     | 
 114 |     |             // Delete the slot where the moved value was stored
 115 | *   |             set._values.pop();
 116 |     | 
 117 |     |             // Delete the tracked position for the deleted slot
 118 | *   |             delete set._positions[value];
 119 |     | 
 120 | *   |             return true;
 121 |     |         } else {
 122 | *   |             return false;
 123 |     |         }
 124 |     |     }
 125 |     | 
 126 |     |     /**
 127 |     |      * @dev Removes all the values from a set. O(n).
 128 |     |      *
 129 |     |      * WARNING: This function has an unbounded cost that scales with set size. Developers should keep in mind that
 130 |     |      * using it may render the function uncallable if the set grows to the point where clearing it consumes too much
 131 |     |      * gas to fit in a block.
 132 |     |      */
 133 |     |     function _clear(Set storage set) private {
 134 |     |         uint256 len = _length(set);
 135 |     |         for (uint256 i = 0; i < len; ++i) {
 136 |     |             delete set._positions[set._values[i]];
 137 |     |         }
 138 |     |         Arrays.unsafeSetLength(set._values, 0);
 139 |     |     }
 140 |     | 
 141 |     |     /**
 142 |     |      * @dev Returns true if the value is in the set. O(1).
 143 |     |      */
 144 | *   |     function _contains(Set storage set, bytes32 value) private view returns (bool) {
 145 | *   |         return set._positions[value] != 0;
 146 |     |     }
 147 |     | 
 148 |     |     /**
 149 |     |      * @dev Returns the number of values on the set. O(1).
 150 |     |      */
 151 | *   |     function _length(Set storage set) private view returns (uint256) {
 152 | *   |         return set._values.length;
 153 |     |     }
 154 |     | 
 155 |     |     /**
 156 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 157 |     |      *
 158 |     |      * Note that there are no guarantees on the ordering of values inside the
 159 |     |      * array, and it may change when more values are added or removed.
 160 |     |      *
 161 |     |      * Requirements:
 162 |     |      *
 163 |     |      * - `index` must be strictly less than {length}.
 164 |     |      */
 165 |     |     function _at(Set storage set, uint256 index) private view returns (bytes32) {
 166 |     |         return set._values[index];
 167 |     |     }
 168 |     | 
 169 |     |     /**
 170 |     |      * @dev Return the entire set in an array
 171 |     |      *
 172 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 173 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 174 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 175 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 176 |     |      */
 177 | *   |     function _values(Set storage set) private view returns (bytes32[] memory) {
 178 | *   |         return set._values;
 179 |     |     }
 180 |     | 
 181 |     |     /**
 182 |     |      * @dev Return a slice of the set in an array
 183 |     |      *
 184 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 185 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 186 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 187 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 188 |     |      */
 189 |     |     function _values(Set storage set, uint256 start, uint256 end) private view returns (bytes32[] memory) {
 190 |     |         unchecked {
 191 |     |             end = Math.min(end, _length(set));
 192 |     |             start = Math.min(start, end);
 193 |     | 
 194 |     |             uint256 len = end - start;
 195 |     |             bytes32[] memory result = new bytes32[](len);
 196 |     |             for (uint256 i = 0; i < len; ++i) {
 197 |     |                 result[i] = Arrays.unsafeAccess(set._values, start + i).value;
 198 |     |             }
 199 |     |             return result;
 200 |     |         }
 201 |     |     }
 202 |     | 
 203 |     |     // Bytes32Set
 204 |     | 
 205 |     |     struct Bytes32Set {
 206 |     |         Set _inner;
 207 |     |     }
 208 |     | 
 209 |     |     /**
 210 |     |      * @dev Add a value to a set. O(1).
 211 |     |      *
 212 |     |      * Returns true if the value was added to the set, that is if it was not
 213 |     |      * already present.
 214 |     |      */
 215 |     |     function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
 216 |     |         return _add(set._inner, value);
 217 |     |     }
 218 |     | 
 219 |     |     /**
 220 |     |      * @dev Removes a value from a set. O(1).
 221 |     |      *
 222 |     |      * Returns true if the value was removed from the set, that is if it was
 223 |     |      * present.
 224 |     |      */
 225 |     |     function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
 226 |     |         return _remove(set._inner, value);
 227 |     |     }
 228 |     | 
 229 |     |     /**
 230 |     |      * @dev Removes all the values from a set. O(n).
 231 |     |      *
 232 |     |      * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
 233 |     |      * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
 234 |     |      */
 235 |     |     function clear(Bytes32Set storage set) internal {
 236 |     |         _clear(set._inner);
 237 |     |     }
 238 |     | 
 239 |     |     /**
 240 |     |      * @dev Returns true if the value is in the set. O(1).
 241 |     |      */
 242 |     |     function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
 243 |     |         return _contains(set._inner, value);
 244 |     |     }
 245 |     | 
 246 |     |     /**
 247 |     |      * @dev Returns the number of values in the set. O(1).
 248 |     |      */
 249 |     |     function length(Bytes32Set storage set) internal view returns (uint256) {
 250 |     |         return _length(set._inner);
 251 |     |     }
 252 |     | 
 253 |     |     /**
 254 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 255 |     |      *
 256 |     |      * Note that there are no guarantees on the ordering of values inside the
 257 |     |      * array, and it may change when more values are added or removed.
 258 |     |      *
 259 |     |      * Requirements:
 260 |     |      *
 261 |     |      * - `index` must be strictly less than {length}.
 262 |     |      */
 263 |     |     function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
 264 |     |         return _at(set._inner, index);
 265 |     |     }
 266 |     | 
 267 |     |     /**
 268 |     |      * @dev Return the entire set in an array
 269 |     |      *
 270 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 271 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 272 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 273 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 274 |     |      */
 275 |     |     function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
 276 |     |         bytes32[] memory store = _values(set._inner);
 277 |     |         bytes32[] memory result;
 278 |     | 
 279 |     |         assembly ("memory-safe") {
 280 |     |             result := store
 281 |     |         }
 282 |     | 
 283 |     |         return result;
 284 |     |     }
 285 |     | 
 286 |     |     /**
 287 |     |      * @dev Return a slice of the set in an array
 288 |     |      *
 289 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 290 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 291 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 292 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 293 |     |      */
 294 |     |     function values(Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
 295 |     |         bytes32[] memory store = _values(set._inner, start, end);
 296 |     |         bytes32[] memory result;
 297 |     | 
 298 |     |         assembly ("memory-safe") {
 299 |     |             result := store
 300 |     |         }
 301 |     | 
 302 |     |         return result;
 303 |     |     }
 304 |     | 
 305 |     |     // AddressSet
 306 |     | 
 307 |     |     struct AddressSet {
 308 |     |         Set _inner;
 309 |     |     }
 310 |     | 
 311 |     |     /**
 312 |     |      * @dev Add a value to a set. O(1).
 313 |     |      *
 314 |     |      * Returns true if the value was added to the set, that is if it was not
 315 |     |      * already present.
 316 |     |      */
 317 | *   |     function add(AddressSet storage set, address value) internal returns (bool) {
 318 | *   |         return _add(set._inner, bytes32(uint256(uint160(value))));
 319 |     |     }
 320 |     | 
 321 |     |     /**
 322 |     |      * @dev Removes a value from a set. O(1).
 323 |     |      *
 324 |     |      * Returns true if the value was removed from the set, that is if it was
 325 |     |      * present.
 326 |     |      */
 327 | *   |     function remove(AddressSet storage set, address value) internal returns (bool) {
 328 | *   |         return _remove(set._inner, bytes32(uint256(uint160(value))));
 329 |     |     }
 330 |     | 
 331 |     |     /**
 332 |     |      * @dev Removes all the values from a set. O(n).
 333 |     |      *
 334 |     |      * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
 335 |     |      * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
 336 |     |      */
 337 |     |     function clear(AddressSet storage set) internal {
 338 |     |         _clear(set._inner);
 339 |     |     }
 340 |     | 
 341 |     |     /**
 342 |     |      * @dev Returns true if the value is in the set. O(1).
 343 |     |      */
 344 | *   |     function contains(AddressSet storage set, address value) internal view returns (bool) {
 345 | *   |         return _contains(set._inner, bytes32(uint256(uint160(value))));
 346 |     |     }
 347 |     | 
 348 |     |     /**
 349 |     |      * @dev Returns the number of values in the set. O(1).
 350 |     |      */
 351 | *   |     function length(AddressSet storage set) internal view returns (uint256) {
 352 | *   |         return _length(set._inner);
 353 |     |     }
 354 |     | 
 355 |     |     /**
 356 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 357 |     |      *
 358 |     |      * Note that there are no guarantees on the ordering of values inside the
 359 |     |      * array, and it may change when more values are added or removed.
 360 |     |      *
 361 |     |      * Requirements:
 362 |     |      *
 363 |     |      * - `index` must be strictly less than {length}.
 364 |     |      */
 365 |     |     function at(AddressSet storage set, uint256 index) internal view returns (address) {
 366 |     |         return address(uint160(uint256(_at(set._inner, index))));
 367 |     |     }
 368 |     | 
 369 |     |     /**
 370 |     |      * @dev Return the entire set in an array
 371 |     |      *
 372 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 373 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 374 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 375 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 376 |     |      */
 377 | *   |     function values(AddressSet storage set) internal view returns (address[] memory) {
 378 | *   |         bytes32[] memory store = _values(set._inner);
 379 |     |         address[] memory result;
 380 |     | 
 381 |     |         assembly ("memory-safe") {
 382 |     |             result := store
 383 |     |         }
 384 |     | 
 385 |     |         return result;
 386 |     |     }
 387 |     | 
 388 |     |     /**
 389 |     |      * @dev Return a slice of the set in an array
 390 |     |      *
 391 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 392 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 393 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 394 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 395 |     |      */
 396 |     |     function values(AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {
 397 |     |         bytes32[] memory store = _values(set._inner, start, end);
 398 |     |         address[] memory result;
 399 |     | 
 400 |     |         assembly ("memory-safe") {
 401 |     |             result := store
 402 |     |         }
 403 |     | 
 404 |     |         return result;
 405 |     |     }
 406 |     | 
 407 |     |     // UintSet
 408 |     | 
 409 |     |     struct UintSet {
 410 |     |         Set _inner;
 411 |     |     }
 412 |     | 
 413 |     |     /**
 414 |     |      * @dev Add a value to a set. O(1).
 415 |     |      *
 416 |     |      * Returns true if the value was added to the set, that is if it was not
 417 |     |      * already present.
 418 |     |      */
 419 |     |     function add(UintSet storage set, uint256 value) internal returns (bool) {
 420 |     |         return _add(set._inner, bytes32(value));
 421 |     |     }
 422 |     | 
 423 |     |     /**
 424 |     |      * @dev Removes a value from a set. O(1).
 425 |     |      *
 426 |     |      * Returns true if the value was removed from the set, that is if it was
 427 |     |      * present.
 428 |     |      */
 429 |     |     function remove(UintSet storage set, uint256 value) internal returns (bool) {
 430 |     |         return _remove(set._inner, bytes32(value));
 431 |     |     }
 432 |     | 
 433 |     |     /**
 434 |     |      * @dev Removes all the values from a set. O(n).
 435 |     |      *
 436 |     |      * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
 437 |     |      * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
 438 |     |      */
 439 |     |     function clear(UintSet storage set) internal {
 440 |     |         _clear(set._inner);
 441 |     |     }
 442 |     | 
 443 |     |     /**
 444 |     |      * @dev Returns true if the value is in the set. O(1).
 445 |     |      */
 446 |     |     function contains(UintSet storage set, uint256 value) internal view returns (bool) {
 447 |     |         return _contains(set._inner, bytes32(value));
 448 |     |     }
 449 |     | 
 450 |     |     /**
 451 |     |      * @dev Returns the number of values in the set. O(1).
 452 |     |      */
 453 |     |     function length(UintSet storage set) internal view returns (uint256) {
 454 |     |         return _length(set._inner);
 455 |     |     }
 456 |     | 
 457 |     |     /**
 458 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 459 |     |      *
 460 |     |      * Note that there are no guarantees on the ordering of values inside the
 461 |     |      * array, and it may change when more values are added or removed.
 462 |     |      *
 463 |     |      * Requirements:
 464 |     |      *
 465 |     |      * - `index` must be strictly less than {length}.
 466 |     |      */
 467 |     |     function at(UintSet storage set, uint256 index) internal view returns (uint256) {
 468 |     |         return uint256(_at(set._inner, index));
 469 |     |     }
 470 |     | 
 471 |     |     /**
 472 |     |      * @dev Return the entire set in an array
 473 |     |      *
 474 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 475 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 476 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 477 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 478 |     |      */
 479 |     |     function values(UintSet storage set) internal view returns (uint256[] memory) {
 480 |     |         bytes32[] memory store = _values(set._inner);
 481 |     |         uint256[] memory result;
 482 |     | 
 483 |     |         assembly ("memory-safe") {
 484 |     |             result := store
 485 |     |         }
 486 |     | 
 487 |     |         return result;
 488 |     |     }
 489 |     | 
 490 |     |     /**
 491 |     |      * @dev Return a slice of the set in an array
 492 |     |      *
 493 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 494 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 495 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 496 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 497 |     |      */
 498 |     |     function values(UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {
 499 |     |         bytes32[] memory store = _values(set._inner, start, end);
 500 |     |         uint256[] memory result;
 501 |     | 
 502 |     |         assembly ("memory-safe") {
 503 |     |             result := store
 504 |     |         }
 505 |     | 
 506 |     |         return result;
 507 |     |     }
 508 |     | 
 509 |     |     struct StringSet {
 510 |     |         // Storage of set values
 511 |     |         string[] _values;
 512 |     |         // Position is the index of the value in the `values` array plus 1.
 513 |     |         // Position 0 is used to mean a value is not in the set.
 514 |     |         mapping(string value => uint256) _positions;
 515 |     |     }
 516 |     | 
 517 |     |     /**
 518 |     |      * @dev Add a value to a set. O(1).
 519 |     |      *
 520 |     |      * Returns true if the value was added to the set, that is if it was not
 521 |     |      * already present.
 522 |     |      */
 523 |     |     function add(StringSet storage set, string memory value) internal returns (bool) {
 524 |     |         if (!contains(set, value)) {
 525 |     |             set._values.push(value);
 526 |     |             // The value is stored at length-1, but we add 1 to all indexes
 527 |     |             // and use 0 as a sentinel value
 528 |     |             set._positions[value] = set._values.length;
 529 |     |             return true;
 530 |     |         } else {
 531 |     |             return false;
 532 |     |         }
 533 |     |     }
 534 |     | 
 535 |     |     /**
 536 |     |      * @dev Removes a value from a set. O(1).
 537 |     |      *
 538 |     |      * Returns true if the value was removed from the set, that is if it was
 539 |     |      * present.
 540 |     |      */
 541 |     |     function remove(StringSet storage set, string memory value) internal returns (bool) {
 542 |     |         // We cache the value's position to prevent multiple reads from the same storage slot
 543 |     |         uint256 position = set._positions[value];
 544 |     | 
 545 |     |         if (position != 0) {
 546 |     |             // Equivalent to contains(set, value)
 547 |     |             // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
 548 |     |             // the array, and then remove the last element (sometimes called as 'swap and pop').
 549 |     |             // This modifies the order of the array, as noted in {at}.
 550 |     | 
 551 |     |             uint256 valueIndex = position - 1;
 552 |     |             uint256 lastIndex = set._values.length - 1;
 553 |     | 
 554 |     |             if (valueIndex != lastIndex) {
 555 |     |                 string memory lastValue = set._values[lastIndex];
 556 |     | 
 557 |     |                 // Move the lastValue to the index where the value to delete is
 558 |     |                 set._values[valueIndex] = lastValue;
 559 |     |                 // Update the tracked position of the lastValue (that was just moved)
 560 |     |                 set._positions[lastValue] = position;
 561 |     |             }
 562 |     | 
 563 |     |             // Delete the slot where the moved value was stored
 564 |     |             set._values.pop();
 565 |     | 
 566 |     |             // Delete the tracked position for the deleted slot
 567 |     |             delete set._positions[value];
 568 |     | 
 569 |     |             return true;
 570 |     |         } else {
 571 |     |             return false;
 572 |     |         }
 573 |     |     }
 574 |     | 
 575 |     |     /**
 576 |     |      * @dev Removes all the values from a set. O(n).
 577 |     |      *
 578 |     |      * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
 579 |     |      * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
 580 |     |      */
 581 |     |     function clear(StringSet storage set) internal {
 582 |     |         uint256 len = length(set);
 583 |     |         for (uint256 i = 0; i < len; ++i) {
 584 |     |             delete set._positions[set._values[i]];
 585 |     |         }
 586 |     |         Arrays.unsafeSetLength(set._values, 0);
 587 |     |     }
 588 |     | 
 589 |     |     /**
 590 |     |      * @dev Returns true if the value is in the set. O(1).
 591 |     |      */
 592 |     |     function contains(StringSet storage set, string memory value) internal view returns (bool) {
 593 |     |         return set._positions[value] != 0;
 594 |     |     }
 595 |     | 
 596 |     |     /**
 597 |     |      * @dev Returns the number of values on the set. O(1).
 598 |     |      */
 599 |     |     function length(StringSet storage set) internal view returns (uint256) {
 600 |     |         return set._values.length;
 601 |     |     }
 602 |     | 
 603 |     |     /**
 604 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 605 |     |      *
 606 |     |      * Note that there are no guarantees on the ordering of values inside the
 607 |     |      * array, and it may change when more values are added or removed.
 608 |     |      *
 609 |     |      * Requirements:
 610 |     |      *
 611 |     |      * - `index` must be strictly less than {length}.
 612 |     |      */
 613 |     |     function at(StringSet storage set, uint256 index) internal view returns (string memory) {
 614 |     |         return set._values[index];
 615 |     |     }
 616 |     | 
 617 |     |     /**
 618 |     |      * @dev Return the entire set in an array
 619 |     |      *
 620 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 621 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 622 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 623 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 624 |     |      */
 625 |     |     function values(StringSet storage set) internal view returns (string[] memory) {
 626 |     |         return set._values;
 627 |     |     }
 628 |     | 
 629 |     |     /**
 630 |     |      * @dev Return a slice of the set in an array
 631 |     |      *
 632 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 633 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 634 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 635 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 636 |     |      */
 637 |     |     function values(StringSet storage set, uint256 start, uint256 end) internal view returns (string[] memory) {
 638 |     |         unchecked {
 639 |     |             end = Math.min(end, length(set));
 640 |     |             start = Math.min(start, end);
 641 |     | 
 642 |     |             uint256 len = end - start;
 643 |     |             string[] memory result = new string[](len);
 644 |     |             for (uint256 i = 0; i < len; ++i) {
 645 |     |                 result[i] = Arrays.unsafeAccess(set._values, start + i).value;
 646 |     |             }
 647 |     |             return result;
 648 |     |         }
 649 |     |     }
 650 |     | 
 651 |     |     struct BytesSet {
 652 |     |         // Storage of set values
 653 |     |         bytes[] _values;
 654 |     |         // Position is the index of the value in the `values` array plus 1.
 655 |     |         // Position 0 is used to mean a value is not in the set.
 656 |     |         mapping(bytes value => uint256) _positions;
 657 |     |     }
 658 |     | 
 659 |     |     /**
 660 |     |      * @dev Add a value to a set. O(1).
 661 |     |      *
 662 |     |      * Returns true if the value was added to the set, that is if it was not
 663 |     |      * already present.
 664 |     |      */
 665 |     |     function add(BytesSet storage set, bytes memory value) internal returns (bool) {
 666 |     |         if (!contains(set, value)) {
 667 |     |             set._values.push(value);
 668 |     |             // The value is stored at length-1, but we add 1 to all indexes
 669 |     |             // and use 0 as a sentinel value
 670 |     |             set._positions[value] = set._values.length;
 671 |     |             return true;
 672 |     |         } else {
 673 |     |             return false;
 674 |     |         }
 675 |     |     }
 676 |     | 
 677 |     |     /**
 678 |     |      * @dev Removes a value from a set. O(1).
 679 |     |      *
 680 |     |      * Returns true if the value was removed from the set, that is if it was
 681 |     |      * present.
 682 |     |      */
 683 |     |     function remove(BytesSet storage set, bytes memory value) internal returns (bool) {
 684 |     |         // We cache the value's position to prevent multiple reads from the same storage slot
 685 |     |         uint256 position = set._positions[value];
 686 |     | 
 687 |     |         if (position != 0) {
 688 |     |             // Equivalent to contains(set, value)
 689 |     |             // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
 690 |     |             // the array, and then remove the last element (sometimes called as 'swap and pop').
 691 |     |             // This modifies the order of the array, as noted in {at}.
 692 |     | 
 693 |     |             uint256 valueIndex = position - 1;
 694 |     |             uint256 lastIndex = set._values.length - 1;
 695 |     | 
 696 |     |             if (valueIndex != lastIndex) {
 697 |     |                 bytes memory lastValue = set._values[lastIndex];
 698 |     | 
 699 |     |                 // Move the lastValue to the index where the value to delete is
 700 |     |                 set._values[valueIndex] = lastValue;
 701 |     |                 // Update the tracked position of the lastValue (that was just moved)
 702 |     |                 set._positions[lastValue] = position;
 703 |     |             }
 704 |     | 
 705 |     |             // Delete the slot where the moved value was stored
 706 |     |             set._values.pop();
 707 |     | 
 708 |     |             // Delete the tracked position for the deleted slot
 709 |     |             delete set._positions[value];
 710 |     | 
 711 |     |             return true;
 712 |     |         } else {
 713 |     |             return false;
 714 |     |         }
 715 |     |     }
 716 |     | 
 717 |     |     /**
 718 |     |      * @dev Removes all the values from a set. O(n).
 719 |     |      *
 720 |     |      * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
 721 |     |      * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
 722 |     |      */
 723 |     |     function clear(BytesSet storage set) internal {
 724 |     |         uint256 len = length(set);
 725 |     |         for (uint256 i = 0; i < len; ++i) {
 726 |     |             delete set._positions[set._values[i]];
 727 |     |         }
 728 |     |         Arrays.unsafeSetLength(set._values, 0);
 729 |     |     }
 730 |     | 
 731 |     |     /**
 732 |     |      * @dev Returns true if the value is in the set. O(1).
 733 |     |      */
 734 |     |     function contains(BytesSet storage set, bytes memory value) internal view returns (bool) {
 735 |     |         return set._positions[value] != 0;
 736 |     |     }
 737 |     | 
 738 |     |     /**
 739 |     |      * @dev Returns the number of values on the set. O(1).
 740 |     |      */
 741 |     |     function length(BytesSet storage set) internal view returns (uint256) {
 742 |     |         return set._values.length;
 743 |     |     }
 744 |     | 
 745 |     |     /**
 746 |     |      * @dev Returns the value stored at position `index` in the set. O(1).
 747 |     |      *
 748 |     |      * Note that there are no guarantees on the ordering of values inside the
 749 |     |      * array, and it may change when more values are added or removed.
 750 |     |      *
 751 |     |      * Requirements:
 752 |     |      *
 753 |     |      * - `index` must be strictly less than {length}.
 754 |     |      */
 755 |     |     function at(BytesSet storage set, uint256 index) internal view returns (bytes memory) {
 756 |     |         return set._values[index];
 757 |     |     }
 758 |     | 
 759 |     |     /**
 760 |     |      * @dev Return the entire set in an array
 761 |     |      *
 762 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 763 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 764 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 765 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 766 |     |      */
 767 |     |     function values(BytesSet storage set) internal view returns (bytes[] memory) {
 768 |     |         return set._values;
 769 |     |     }
 770 |     | 
 771 |     |     /**
 772 |     |      * @dev Return a slice of the set in an array
 773 |     |      *
 774 |     |      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
 775 |     |      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
 776 |     |      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
 777 |     |      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
 778 |     |      */
 779 |     |     function values(BytesSet storage set, uint256 start, uint256 end) internal view returns (bytes[] memory) {
 780 |     |         unchecked {
 781 |     |             end = Math.min(end, length(set));
 782 |     |             start = Math.min(start, end);
 783 |     | 
 784 |     |             uint256 len = end - start;
 785 |     |             bytes[] memory result = new bytes[](len);
 786 |     |             for (uint256 i = 0; i < len; ++i) {
 787 |     |                 result[i] = Arrays.unsafeAccess(set._values, start + i).value;
 788 |     |             }
 789 |     |             return result;
 790 |     |         }
 791 |     |     }
 792 |     | }
 793 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/BaseHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // External
   5 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   6 |     | 
   7 |     | // Superform
   8 |     | import { HookDataDecoder } from "../libraries/HookDataDecoder.sol";
   9 |     | import { ISuperHook, ISuperHookSetter, ISuperHookResult, ISuperHookInspector } from "../interfaces/ISuperHook.sol";
  10 |     | 
  11 |     | /// @title BaseHook
  12 |     | /// @author Superform Labs
  13 |     | /// @notice Base implementation for all hooks in the Superform system
  14 |     | /// @dev Provides core security validation and execution flow management for hooks
  15 |     | ///      All specialized hooks should inherit from this base contract
  16 |     | ///      Implements the ISuperHook interface defined lifecycle methods
  17 |     | ///      Uses a transient storage pattern for stateful execution context
  18 |     | abstract contract BaseHook is ISuperHook, ISuperHookSetter, ISuperHookResult, ISuperHookInspector {
  19 |     |     using HookDataDecoder for bytes;
  20 |     | 
  21 |     |     /*//////////////////////////////////////////////////////////////
  22 |     |                                  STORAGE
  23 |     |     //////////////////////////////////////////////////////////////*/
  24 |     | 
  25 |     |     /// @notice The number of shares used by this hook's operation
  26 |     |     /// @dev Used for accounting and tracking consumption of position shares
  27 |     |     uint256 public transient usedShares;
  28 |     | 
  29 |     |     /// @notice The special token address (if any) associated with this hook's operation
  30 |     |     /// @dev May be used to track token addresses for various operations
  31 |     |     address public transient spToken;
  32 |     | 
  33 |     |     /// @notice The primary asset address this hook operates on
  34 |     |     /// @dev Typically the base token or asset being processed
  35 |     |     address public transient asset;
  36 |     | 
  37 |     |     /// @notice Execution nonce for creating unique contexts
  38 | *   |     uint256 public transient executionNonce;
  39 |     | 
  40 |     |     /// @notice Last execution context caller
  41 |     |     address public transient lastCaller;
  42 |     | 
  43 |     |     // Storage offsets for different state variables
  44 | *   |     uint256 private constant OUT_AMOUNT_OFFSET = 1;
  45 | *   |     uint256 private constant PRE_EXECUTE_MUTEX_OFFSET = 2;
  46 | *   |     uint256 private constant POST_EXECUTE_MUTEX_OFFSET = 3;
  47 |     | 
  48 |     |     /// @notice Base storage key for hook execution state
  49 | *   |     bytes32 private constant HOOK_EXECUTION_STORAGE = keccak256("hook.execution.state");
  50 |     | 
  51 |     |     /// @notice Storage key for account context mapping
  52 | *   |     bytes32 private constant ACCOUNT_CONTEXT_STORAGE = keccak256("hook.account.context");
  53 |     | 
  54 |     |     /// @notice The specific subtype identifier for this hook
  55 |     |     /// @dev Used to identify specialized hook types beyond the basic HookType enum
  56 |     |     bytes32 public immutable SUB_TYPE;
  57 |     | 
  58 |     |     /// @notice The type of hook (NONACCOUNTING, INFLOW, OUTFLOW)
  59 |     |     /// @dev Determines how the hook impacts accounting in the system
  60 | *   |     ISuperHook.HookType public hookType;
  61 |     | 
  62 |     |     /*//////////////////////////////////////////////////////////////
  63 |     |                                  ERRORS
  64 |     |     //////////////////////////////////////////////////////////////*/
  65 |     |     /// @notice Thrown when a caller attempts to execute hook methods without proper authorization
  66 |     |     /// @dev Used by security validation to prevent unauthorized hook execution
  67 |     |     error NOT_AUTHORIZED();
  68 |     | 
  69 |     |     /// @notice Thrown when an amount parameter is invalid (e.g., zero or overflow)
  70 |     |     /// @dev Used in validation checks for asset amounts and share values
  71 |     |     error AMOUNT_NOT_VALID();
  72 |     | 
  73 |     |     /// @notice Thrown when an address parameter is invalid (e.g., zero address)
  74 |     |     /// @dev Used in validation checks for tokens, accounts, and other addresses
  75 |     |     error ADDRESS_NOT_VALID();
  76 |     | 
  77 |     |     /// @notice Thrown when a caller is not authorized to execute hook methods
  78 |     |     /// @dev Used by security validation to prevent unauthorized hook execution
  79 |     |     error UNAUTHORIZED_CALLER();
  80 |     | 
  81 |     |     /// @notice Thrown when preExecute is called more than once
  82 |     |     /// @dev Used to prevent reentrancy attacks and ensure proper execution flow
  83 |     |     error PRE_EXECUTE_ALREADY_CALLED();
  84 |     | 
  85 |     |     /// @notice Thrown when postExecute is called more than once
  86 |     |     /// @dev Used to prevent reentrancy attacks and ensure proper execution flow
  87 |     |     error POST_EXECUTE_ALREADY_CALLED();
  88 |     | 
  89 |     |     /// @notice Thrown when a hook execution is incomplete
  90 |     |     /// @dev Used to prevent incomplete hook execution
  91 |     |     error INCOMPLETE_HOOK_EXECUTION();
  92 |     | 
  93 |     |     /// @notice Thrown when trying to set outAmount after preExecute or postExecute
  94 |     |     /// @dev Used to prevent setting outAmount after preExecute or postExecute
  95 |     |     error CANNOT_SET_OUT_AMOUNT();
  96 |     | 
  97 |     |     /// @notice Initializes the hook with its type and subtype
  98 |     |     /// @dev Sets immutable parameters that define the hook's behavior
  99 |     |     /// @param hookType_ The type classification for this hook (NONACCOUNTING, INFLOW, OUTFLOW)
 100 |     |     /// @param subType_ The specific subtype identifier for specialized hook functionality
 101 |     |     constructor(ISuperHook.HookType hookType_, bytes32 subType_) {
 102 | *   |         hookType = hookType_;
 103 | *   |         SUB_TYPE = subType_;
 104 |     |     }
 105 |     | 
 106 |     |     modifier onlyLastCaller() {
 107 | *   |         if (msg.sender != lastCaller) revert UNAUTHORIZED_CALLER();
 108 |     |         _;
 109 |     |     }
 110 |     | 
 111 |     |     /*//////////////////////////////////////////////////////////////
 112 |     |                           EXECUTION SECURITY
 113 |     |     //////////////////////////////////////////////////////////////*/
 114 |     |     /// @inheritdoc ISuperHook
 115 | *   |     function setExecutionContext(address caller) external {
 116 | *   |         _createExecutionContext(caller);
 117 | *   |         lastCaller = msg.sender;
 118 |     |     }
 119 |     | 
 120 |     |     /// @dev Standard build pattern - MUST include preExecute first, postExecute last
 121 |     |     /// @inheritdoc ISuperHook
 122 | *   |     function build(
 123 |     |         address prevHook,
 124 |     |         address account,
 125 |     |         bytes calldata hookData
 126 |     |     )
 127 |     |         external
 128 |     |         view
 129 |     |         virtual
 130 | *   |         returns (Execution[] memory executions)
 131 | *   |     {
 132 |     |         // Get hook-specific executions
 133 | *   |         Execution[] memory hookExecutions = _buildHookExecutions(prevHook, account, hookData);
 134 |     | 
 135 |     |         // Always include pre + hook + post
 136 | *   |         executions = new Execution[](hookExecutions.length + 2);
 137 |     | 
 138 |     |         // FIRST: preExecute
 139 | *   |         executions[0] = Execution({
 140 | *   |             target: address(this),
 141 | *   |             value: 0,
 142 | *   |             callData: abi.encodeCall(this.preExecute, (prevHook, account, hookData))
 143 |     |         });
 144 |     | 
 145 |     |         // MIDDLE: hook-specific operations
 146 | *   |         for (uint256 i = 0; i < hookExecutions.length; i++) {
 147 | *   |             executions[i + 1] = hookExecutions[i];
 148 |     |         }
 149 |     | 
 150 |     |         // LAST: postExecute
 151 | *   |         executions[executions.length - 1] = Execution({
 152 | *   |             target: address(this),
 153 | *   |             value: 0,
 154 | *   |             callData: abi.encodeCall(this.postExecute, (prevHook, account, hookData))
 155 |     |         });
 156 |     |     }
 157 |     | 
 158 |     |     /// @inheritdoc ISuperHook
 159 | *   |     function preExecute(address prevHook, address account, bytes calldata data) external {
 160 | *   |         if (msg.sender != account) revert UNAUTHORIZED_CALLER();
 161 | *   |         uint256 context = _getCurrentExecutionContext(account);
 162 | *   |         if (_getPreExecuteMutex(context)) revert PRE_EXECUTE_ALREADY_CALLED();
 163 | *   |         _setPreExecuteMutex(context, true);
 164 | *   |         _preExecute(prevHook, account, data);
 165 |     |     }
 166 |     | 
 167 |     |     /// @inheritdoc ISuperHook
 168 | *   |     function postExecute(address prevHook, address account, bytes calldata data) external {
 169 | *   |         if (msg.sender != account) revert UNAUTHORIZED_CALLER();
 170 | *   |         uint256 context = _getCurrentExecutionContext(account);
 171 | *   |         if (_getPostExecuteMutex(context)) revert POST_EXECUTE_ALREADY_CALLED();
 172 | *   |         _setPostExecuteMutex(context, true);
 173 | *   |         _postExecute(prevHook, account, data);
 174 |     |     }
 175 |     | 
 176 |     |     /// @inheritdoc ISuperHookSetter
 177 | *   |     function setOutAmount(uint256 _outAmount, address caller) external {
 178 |     |         uint256 context = _getCurrentExecutionContext(caller);
 179 |     |         if (_getPreExecuteMutex(context) || _getPostExecuteMutex(context)) {
 180 |     |             revert CANNOT_SET_OUT_AMOUNT();
 181 |     |         }
 182 |     | 
 183 | *   |         bytes32 key = _makeKey(context, OUT_AMOUNT_OFFSET);
 184 | *   |         assembly {
 185 | *   |             tstore(key, _outAmount)
 186 |     |         }
 187 |     |     }
 188 |     | 
 189 | *   |     function getOutAmount(address caller) public view returns (uint256) {
 190 | *   |         return _getOutAmount(_getCurrentExecutionContext(caller));
 191 |     |     }
 192 |     | 
 193 |     |     /// @inheritdoc ISuperHook
 194 | *   |     function resetExecutionState(address caller) external onlyLastCaller {
 195 | *   |         uint256 context = _getCurrentExecutionContext(caller);
 196 | *   |         if (!_getPreExecuteMutex(context) || !_getPostExecuteMutex(context)) {
 197 |     |             revert INCOMPLETE_HOOK_EXECUTION();
 198 |     |         }
 199 |     | 
 200 | *   |         _clearExecutionState(context);
 201 |     |     }
 202 |     | 
 203 |     |     /*//////////////////////////////////////////////////////////////
 204 |     |                                  VIEW METHODS
 205 |     |     //////////////////////////////////////////////////////////////*/
 206 |     |     /// @inheritdoc ISuperHook
 207 |     |     function subtype() external view returns (bytes32) {
 208 |     |         return SUB_TYPE;
 209 |     |     }
 210 |     | 
 211 |     |     /// @inheritdoc ISuperHookInspector
 212 |     |     function inspect(bytes calldata) external view virtual returns (bytes memory) { }
 213 |     | 
 214 |     |     /*//////////////////////////////////////////////////////////////
 215 |     |                                  INTERNAL METHODS
 216 |     |     //////////////////////////////////////////////////////////////*/
 217 |     |     /// @notice Internal implementation of build
 218 |     |     /// @dev Abstract function to be implemented by derived hooks
 219 |     |     ///      Called during build to generate hook-specific execution sequences
 220 |     |     /// @param prevHook The previous hook in the chain, or address(0) if first hook
 221 |     |     /// @param account The account that operations will be performed for
 222 |     |     /// @param data Hook-specific parameters and configuration data
 223 |     |     /// @return executions Array of execution objects containing target, value, and callData
 224 |     |     function _buildHookExecutions(
 225 |     |         address prevHook,
 226 |     |         address account,
 227 |     |         bytes calldata data
 228 |     |     )
 229 |     |         internal
 230 |     |         view
 231 |     |         virtual
 232 |     |         returns (Execution[] memory executions);
 233 |     | 
 234 |     |     /// @notice Internal implementation of preExecute
 235 |     |     /// @dev Abstract function to be implemented by derived hooks
 236 |     |     ///      Called before execution to validate inputs and prepare the hook's state
 237 |     |     ///      Typically sets up the hook context by parsing parameters from data
 238 |     |     ///      May check balances, permissions, or other preconditions
 239 |     |     /// @param prevHook The previous hook in the chain, or address(0) if first hook
 240 |     |     /// @param account The account that operations will be performed for
 241 |     |     /// @param data Hook-specific parameters and configuration data
 242 |     |     function _preExecute(address prevHook, address account, bytes calldata data) internal virtual { }
 243 |     | 
 244 |     |     /// @notice Internal implementation of postExecute
 245 |     |     /// @dev Abstract function to be implemented by derived hooks
 246 |     |     ///      Called after execution to finalize the hook's state and set output values
 247 |     |     ///      Typically calculates final results and sets outAmount, usedShares, etc.
 248 |     |     ///      May perform additional validations on execution results
 249 |     |     /// @param prevHook The previous hook in the chain, or address(0) if first hook
 250 |     |     /// @param account The account operations were performed for
 251 |     |     /// @param data Hook-specific parameters and configuration data
 252 |     |     function _postExecute(address prevHook, address account, bytes calldata data) internal virtual { }
 253 |     | 
 254 |     |     /// @notice Decodes a boolean value from a byte array at the specified offset
 255 |     |     /// @dev Helper function for extracting boolean values from packed data
 256 |     |     ///      Used when parsing hook-specific data parameters
 257 |     |     /// @param data The byte array containing the encoded data
 258 |     |     /// @param offset The position in the array to read from
 259 |     |     /// @return The decoded boolean value (true if byte is non-zero)
 260 | *   |     function _decodeBool(bytes memory data, uint256 offset) internal pure returns (bool) {
 261 | *   |         return data[offset] != 0;
 262 |     |     }
 263 |     | 
 264 |     |     /// @notice Replaces an amount value within a byte array at the specified offset
 265 |     |     /// @dev Used to modify hook calldata for amount adjustments without full re-encoding
 266 |     |     ///      Particularly useful for modifying amounts in multi-hook execution chains
 267 |     |     ///      Directly modifies the bytes in-place for gas efficiency
 268 |     |     /// @param data The original byte array containing encoded calldata
 269 |     |     /// @param amount The new amount value to insert
 270 |     |     /// @param offset The position in the array where the amount starts
 271 |     |     /// @return The modified byte array with the replaced amount
 272 | *   |     function _replaceCalldataAmount(
 273 |     |         bytes memory data,
 274 |     |         uint256 amount,
 275 |     |         uint256 offset
 276 |     |     )
 277 |     |         internal
 278 |     |         pure
 279 | *   |         returns (bytes memory)
 280 |     |     {
 281 | *   |         bytes memory newAmountEncoded = abi.encodePacked(amount);
 282 | *   |         for (uint256 i; i < 32; ++i) {
 283 | *   |             data[offset + i] = newAmountEncoded[i];
 284 |     |         }
 285 | *   |         return data;
 286 |     |     }
 287 |     | 
 288 | *   |     function _makeAccountContextKey(address account) private pure returns (bytes32) {
 289 | *   |         return keccak256(abi.encodePacked(ACCOUNT_CONTEXT_STORAGE, account));
 290 |     |     }
 291 |     | 
 292 | *   |     function _createExecutionContext(address caller) private returns (uint256) {
 293 |     |         // Always increment nonce for new execution context
 294 | *   |         executionNonce++;
 295 | *   |         bytes32 key = _makeAccountContextKey(caller);
 296 |     | 
 297 |     |         // Store this context for the current caller
 298 | *   |         uint256 currentNonce = executionNonce; // Load into local variable for assembly
 299 |     |         assembly {
 300 | *   |             tstore(key, currentNonce)
 301 |     |         }
 302 |     | 
 303 | *   |         return executionNonce;
 304 |     |     }
 305 |     | 
 306 | *   |     function _getCurrentExecutionContext(address caller) private view returns (uint256 context) {
 307 | *   |         bytes32 key = _makeAccountContextKey(caller);
 308 |     |         assembly {
 309 | *   |             context := tload(key)
 310 |     |         }
 311 |     |     }
 312 |     | 
 313 | *   |     function _makeKey(uint256 context, uint256 offset) private pure returns (bytes32) {
 314 | *   |         return keccak256(abi.encodePacked(HOOK_EXECUTION_STORAGE, context, offset));
 315 |     |     }
 316 |     | 
 317 | *   |     function _getOutAmount(uint256 context) private view returns (uint256 value) {
 318 | *   |         bytes32 key = _makeKey(context, OUT_AMOUNT_OFFSET);
 319 |     |         assembly {
 320 |     |             value := tload(key)
 321 |     |         }
 322 |     |     }
 323 |     | 
 324 | *   |     function _setOutAmount(uint256 value, address caller) internal {
 325 | *   |         uint256 context = _getCurrentExecutionContext(caller);
 326 | *   |         bytes32 key = _makeKey(context, OUT_AMOUNT_OFFSET);
 327 |     |         assembly {
 328 |     |             tstore(key, value)
 329 |     |         }
 330 |     |     }
 331 |     | 
 332 | *   |     function _getPreExecuteMutex(uint256 context) private view returns (bool value) {
 333 | *   |         bytes32 key = _makeKey(context, PRE_EXECUTE_MUTEX_OFFSET);
 334 |     |         assembly {
 335 |     |             value := tload(key)
 336 |     |         }
 337 |     |     }
 338 |     | 
 339 | *   |     function _setPreExecuteMutex(uint256 context, bool value) private {
 340 | *   |         bytes32 key = _makeKey(context, PRE_EXECUTE_MUTEX_OFFSET);
 341 |     |         assembly {
 342 |     |             tstore(key, value)
 343 |     |         }
 344 |     |     }
 345 |     | 
 346 | *   |     function _getPostExecuteMutex(uint256 context) private view returns (bool value) {
 347 | *   |         bytes32 key = _makeKey(context, POST_EXECUTE_MUTEX_OFFSET);
 348 |     |         assembly {
 349 |     |             value := tload(key)
 350 |     |         }
 351 |     |     }
 352 |     | 
 353 | *   |     function _setPostExecuteMutex(uint256 context, bool value) private {
 354 | *   |         bytes32 key = _makeKey(context, POST_EXECUTE_MUTEX_OFFSET);
 355 | *   |         assembly {
 356 | *   |             tstore(key, value)
 357 |     |         }
 358 |     |     }
 359 |     | 
 360 | *   |     function _clearExecutionState(uint256 context) private {
 361 | *   |         _setPreExecuteMutex(context, false);
 362 | *   |         _setPostExecuteMutex(context, false);
 363 |     |     }
 364 |     | }
 365 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/VaultBankLockableHook.sol
  1 |     | // SPDX-License-Identifier: Apache-2.0
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | import { HookDataDecoder } from "../libraries/HookDataDecoder.sol";
  5 |     | 
  6 |     | /// @title VaultBankLockableHook
  7 |     | /// @author Superform Labs
  8 |     | /// @notice Base implementation for all vault bank lockable hooks in the Superform system
  9 |     | abstract contract VaultBankLockableHook {
 10 |     |     using HookDataDecoder for bytes;
 11 |     | 
 12 |     |     /// @notice The vault bank address (if applicable) for cross-chain operations
 13 |     |     /// @dev Used primarily in bridge hooks to track source/destination vault banks
 14 |     |     address public transient vaultBank;
 15 |     | 
 16 |     |     /// @notice The destination chain ID for cross-chain operations
 17 |     |     /// @dev Used primarily in bridge hooks to track target chain
 18 |     |     uint256 public transient dstChainId;
 19 |     | }
 20 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/4626/ApproveAndDeposit4626VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   8 |     | import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import { VaultBankLockableHook } from "../../VaultBankLockableHook.sol";
  13 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  14 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  15 |     | import {
  16 |     |     ISuperHookResult,
  17 |     |     ISuperHookInflowOutflow,
  18 |     |     ISuperHookContextAware,
  19 |     |     ISuperHookInspector
  20 |     | } from "../../../interfaces/ISuperHook.sol";
  21 |     | 
  22 |     | /// @title ApproveAndDeposit4626VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @notice This hook does not support tokens reverting on 0 approval
  25 |     | /// @dev data has the following structure
  26 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  27 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  28 |     | /// @notice         address token = BytesLib.toAddress(data, 52);
  29 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 72);
  30 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 104);
  31 | *   | contract ApproveAndDeposit4626VaultHook is
  32 |     |     BaseHook,
  33 |     |     VaultBankLockableHook,
  34 |     |     ISuperHookInflowOutflow,
  35 |     |     ISuperHookContextAware
  36 |     | {
  37 |     |     using HookDataDecoder for bytes;
  38 |     | 
  39 | *   |     uint256 private constant AMOUNT_POSITION = 72;
  40 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 104;
  41 |     | 
  42 | *   |     constructor() BaseHook(HookType.INFLOW, HookSubTypes.ERC4626) { }
  43 |     | 
  44 |     |     /*//////////////////////////////////////////////////////////////
  45 |     |                                  VIEW METHODS
  46 |     |     //////////////////////////////////////////////////////////////*/
  47 |     |     /// @inheritdoc BaseHook
  48 | *   |     function _buildHookExecutions(
  49 |     |         address prevHook,
  50 |     |         address account,
  51 |     |         bytes calldata data
  52 |     |     )
  53 |     |         internal
  54 |     |         view
  55 |     |         override
  56 | *   |         returns (Execution[] memory executions)
  57 | *   |     {
  58 | *   |         address yieldSource = data.extractYieldSource();
  59 | *   |         address token = BytesLib.toAddress(data, 52);
  60 | *   |         uint256 amount = _decodeAmount(data);
  61 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  62 |     | 
  63 | *   |         if (usePrevHookAmount) {
  64 | *   |             amount = ISuperHookResult(prevHook).getOutAmount(account);
  65 |     |         }
  66 |     | 
  67 | *   |         if (amount == 0) revert AMOUNT_NOT_VALID();
  68 | *   |         if (yieldSource == address(0) || token == address(0)) revert ADDRESS_NOT_VALID();
  69 |     | 
  70 | *   |         executions = new Execution[](4);
  71 | *   |         executions[0] =
  72 | *   |             Execution({ target: token, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, 0)) });
  73 | *   |         executions[1] =
  74 | *   |             Execution({ target: token, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, amount)) });
  75 | *   |         executions[2] =
  76 | *   |             Execution({ target: yieldSource, value: 0, callData: abi.encodeCall(IERC4626.deposit, (amount, account)) });
  77 | *   |         executions[3] =
  78 | *   |             Execution({ target: token, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, 0)) });
  79 |     |     }
  80 |     | 
  81 |     |     /*//////////////////////////////////////////////////////////////
  82 |     |                                  EXTERNAL METHODS
  83 |     |     //////////////////////////////////////////////////////////////*/
  84 |     | 
  85 |     |     /// @inheritdoc ISuperHookInflowOutflow
  86 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  87 |     |         return _decodeAmount(data);
  88 |     |     }
  89 |     | 
  90 |     |     /// @inheritdoc ISuperHookContextAware
  91 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  92 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  93 |     |     }
  94 |     | 
  95 |     |     /// @inheritdoc ISuperHookInspector
  96 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  97 | *   |         return abi.encodePacked(
  98 | *   |             data.extractYieldSource(),
  99 | *   |             BytesLib.toAddress(data, 52) //token
 100 |     |         );
 101 |     |     }
 102 |     | 
 103 |     |     /*//////////////////////////////////////////////////////////////
 104 |     |                                  INTERNAL METHODS
 105 |     |     //////////////////////////////////////////////////////////////*/
 106 | *   |     function _preExecute(address, address account, bytes calldata data) internal override {
 107 |     |         // store current balance
 108 | *   |         _setOutAmount(_getBalance(account, data), account);
 109 | *   |         spToken = data.extractYieldSource();
 110 |     |     }
 111 |     | 
 112 | *   |     function _postExecute(address, address account, bytes calldata data) internal override {
 113 | *   |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 114 |     |     }
 115 |     | 
 116 |     |     /*//////////////////////////////////////////////////////////////
 117 |     |                                  PRIVATE METHODS
 118 |     |     //////////////////////////////////////////////////////////////*/
 119 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 120 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 121 |     |     }
 122 |     | 
 123 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 124 | *   |         return IERC4626(data.extractYieldSource()).balanceOf(account);
 125 |     |     }
 126 |     | }
 127 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/4626/Deposit4626VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol";
   8 |     | 
   9 |     | // Superform
  10 |     | import { BaseHook } from "../../BaseHook.sol";
  11 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  12 |     | import { VaultBankLockableHook } from "../../VaultBankLockableHook.sol";
  13 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  14 |     | import {
  15 |     |     ISuperHookResult,
  16 |     |     ISuperHookInflowOutflow,
  17 |     |     ISuperHookContextAware,
  18 |     |     ISuperHookInspector
  19 |     | } from "../../../interfaces/ISuperHook.sol";
  20 |     | 
  21 |     | /// @title Deposit4626VaultHook
  22 |     | /// @author Superform Labs
  23 |     | /// @dev data has the following structure
  24 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  25 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  26 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 52);
  27 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 84);
  28 | *   | contract Deposit4626VaultHook is BaseHook, VaultBankLockableHook, ISuperHookInflowOutflow, ISuperHookContextAware {
  29 |     |     using HookDataDecoder for bytes;
  30 |     | 
  31 | *   |     uint256 private constant AMOUNT_POSITION = 52;
  32 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 84;
  33 |     | 
  34 | *   |     constructor() BaseHook(HookType.INFLOW, HookSubTypes.ERC4626) { }
  35 |     |     /*//////////////////////////////////////////////////////////////
  36 |     |                                  VIEW METHODS
  37 |     |     //////////////////////////////////////////////////////////////*/
  38 |     |     /// @inheritdoc BaseHook
  39 |     | 
  40 | *   |     function _buildHookExecutions(
  41 |     |         address prevHook,
  42 |     |         address account,
  43 |     |         bytes calldata data
  44 |     |     )
  45 |     |         internal
  46 |     |         view
  47 |     |         override
  48 | *   |         returns (Execution[] memory executions)
  49 |     |     {
  50 | *   |         address yieldSource = data.extractYieldSource();
  51 | *   |         uint256 amount = _decodeAmount(data);
  52 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  53 |     | 
  54 | *   |         if (usePrevHookAmount) {
  55 | *   |             amount = ISuperHookResult(prevHook).getOutAmount(account);
  56 |     |         }
  57 |     | 
  58 | *   |         if (amount == 0) revert AMOUNT_NOT_VALID();
  59 |     |         if (yieldSource == address(0)) revert ADDRESS_NOT_VALID();
  60 |     | 
  61 |     |         executions = new Execution[](1);
  62 |     |         executions[0] =
  63 |     |             Execution({ target: yieldSource, value: 0, callData: abi.encodeCall(IERC4626.deposit, (amount, account)) });
  64 |     |     }
  65 |     | 
  66 |     |     /*//////////////////////////////////////////////////////////////
  67 |     |                                  EXTERNAL METHODS
  68 |     |     //////////////////////////////////////////////////////////////*/
  69 |     | 
  70 |     |     /// @inheritdoc ISuperHookInflowOutflow
  71 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  72 |     |         return _decodeAmount(data);
  73 |     |     }
  74 |     | 
  75 |     |     /// @inheritdoc ISuperHookContextAware
  76 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  77 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  78 |     |     }
  79 |     | 
  80 |     |     /// @inheritdoc ISuperHookInspector
  81 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  82 | *   |         return abi.encodePacked(data.extractYieldSource());
  83 |     |     }
  84 |     | 
  85 |     |     /*//////////////////////////////////////////////////////////////
  86 |     |                                  INTERNAL METHODS
  87 |     |     //////////////////////////////////////////////////////////////*/
  88 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
  89 |     |         // store current balance
  90 |     |         _setOutAmount(_getBalance(account, data), account);
  91 |     |         spToken = data.extractYieldSource();
  92 |     |     }
  93 |     | 
  94 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
  95 |     |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
  96 |     |     }
  97 |     | 
  98 |     |     /*//////////////////////////////////////////////////////////////
  99 |     |                                  PRIVATE METHODS
 100 |     |     //////////////////////////////////////////////////////////////*/
 101 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 102 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 103 |     |     }
 104 |     | 
 105 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 106 | *   |         return IERC4626(data.extractYieldSource()).balanceOf(account);
 107 |     |     }
 108 |     | }
 109 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/4626/Redeem4626VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol";
   8 |     | import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import {
  13 |     |     ISuperHookResultOutflow,
  14 |     |     ISuperHookInflowOutflow,
  15 |     |     ISuperHookOutflow,
  16 |     |     ISuperHookContextAware,
  17 |     |     ISuperHookInspector
  18 |     | } from "../../../interfaces/ISuperHook.sol";
  19 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  20 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  21 |     | 
  22 |     | /// @title Redeem4626VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @dev data has the following structure
  25 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  26 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  27 |     | /// @notice         address owner = BytesLib.toAddress(data, 52);
  28 |     | /// @notice         uint256 shares = BytesLib.toUint256(data, 72);
  29 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 104);
  30 | *   | contract Redeem4626VaultHook is BaseHook, ISuperHookInflowOutflow, ISuperHookOutflow, ISuperHookContextAware {
  31 |     |     using HookDataDecoder for bytes;
  32 |     | 
  33 | *   |     uint256 private constant AMOUNT_POSITION = 72;
  34 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 104;
  35 |     | 
  36 | *   |     constructor() BaseHook(HookType.OUTFLOW, HookSubTypes.ERC4626) { }
  37 |     | 
  38 |     |     /*//////////////////////////////////////////////////////////////
  39 |     |                                  VIEW METHODS
  40 |     |     //////////////////////////////////////////////////////////////*/
  41 |     |     /// @inheritdoc BaseHook
  42 | *   |     function _buildHookExecutions(
  43 |     |         address prevHook,
  44 |     |         address account,
  45 |     |         bytes calldata data
  46 |     |     )
  47 |     |         internal
  48 |     |         view
  49 |     |         override
  50 | *   |         returns (Execution[] memory executions)
  51 | *   |     {
  52 | *   |         address yieldSource = data.extractYieldSource();
  53 | *   |         address owner = BytesLib.toAddress(data, 52);
  54 | *   |         uint256 shares = _decodeAmount(data);
  55 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  56 |     | 
  57 | *   |         if (usePrevHookAmount) {
  58 | *   |             shares = ISuperHookResultOutflow(prevHook).getOutAmount(account);
  59 |     |         }
  60 |     | 
  61 | *   |         if (shares == 0) revert AMOUNT_NOT_VALID();
  62 | *   |         if (yieldSource == address(0)) revert ADDRESS_NOT_VALID();
  63 |     | 
  64 | *   |         executions = new Execution[](1);
  65 | *   |         executions[0] = Execution({
  66 |     |             target: yieldSource,
  67 |     |             value: 0,
  68 | *   |             callData: abi.encodeCall(IERC4626.redeem, (shares, account, owner))
  69 |     |         });
  70 |     |     }
  71 |     | 
  72 |     |     /*//////////////////////////////////////////////////////////////
  73 |     |                                  EXTERNAL METHODS
  74 |     |     //////////////////////////////////////////////////////////////*/
  75 |     | 
  76 |     |     /// @inheritdoc ISuperHookInflowOutflow
  77 | *   |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  78 | *   |         return _decodeAmount(data);
  79 |     |     }
  80 |     | 
  81 |     |     /// @inheritdoc ISuperHookContextAware
  82 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  83 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  84 |     |     }
  85 |     | 
  86 |     |     /// @inheritdoc ISuperHookOutflow
  87 | *   |     function replaceCalldataAmount(bytes memory data, uint256 amount) external pure returns (bytes memory) {
  88 | *   |         return _replaceCalldataAmount(data, amount, AMOUNT_POSITION);
  89 |     |     }
  90 |     | 
  91 |     |     /// @inheritdoc ISuperHookInspector
  92 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  93 | *   |         return abi.encodePacked(
  94 | *   |             data.extractYieldSource(),
  95 | *   |             BytesLib.toAddress(data, 52) // owner
  96 |     |         );
  97 |     |     }
  98 |     | 
  99 |     |     /*//////////////////////////////////////////////////////////////
 100 |     |                                  INTERNAL METHODS
 101 |     |     //////////////////////////////////////////////////////////////*/
 102 | *   |     function _preExecute(address, address account, bytes calldata data) internal override {
 103 | *   |         address yieldSource = data.extractYieldSource();
 104 | *   |         asset = IERC4626(yieldSource).asset();
 105 | *   |         _setOutAmount(_getBalance(account, data), account);
 106 | *   |         usedShares = _getSharesBalance(account, data);
 107 | *   |         spToken = yieldSource;
 108 |     |     }
 109 |     | 
 110 | *   |     function _postExecute(address, address account, bytes calldata data) internal override {
 111 | *   |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 112 | *   |         usedShares = usedShares - _getSharesBalance(account, data);
 113 |     |     }
 114 |     | 
 115 |     |     /*//////////////////////////////////////////////////////////////
 116 |     |                                  PRIVATE METHODS
 117 |     |     //////////////////////////////////////////////////////////////*/
 118 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 119 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 120 |     |     }
 121 |     | 
 122 | *   |     function _getBalance(address account, bytes memory) private view returns (uint256) {
 123 | *   |         return IERC20(asset).balanceOf(account);
 124 |     |     }
 125 |     | 
 126 | *   |     function _getSharesBalance(address account, bytes memory data) private view returns (uint256) {
 127 | *   |         address yieldSource = data.extractYieldSource();
 128 | *   |         address owner = BytesLib.toAddress(data, 52);
 129 | *   |         if (owner == address(0)) {
 130 |     |             owner = account;
 131 |     |         }
 132 | *   |         return IERC4626(yieldSource).balanceOf(owner);
 133 |     |     }
 134 |     | }
 135 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/5115/ApproveAndDeposit5115VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
   8 |     | import { IStandardizedYield } from "../../../vendor/pendle/IStandardizedYield.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import { VaultBankLockableHook } from "../../VaultBankLockableHook.sol";
  13 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  14 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  15 |     | import {
  16 |     |     ISuperHookResult,
  17 |     |     ISuperHookInflowOutflow,
  18 |     |     ISuperHookContextAware,
  19 |     |     ISuperHookInspector
  20 |     | } from "../../../interfaces/ISuperHook.sol";
  21 |     | 
  22 |     | /// @title ApproveAndDeposit5115VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @notice This hook does not support tokens reverting on 0 approval
  25 |     | /// @dev data has the following structure
  26 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  27 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  28 |     | /// @notice         address tokenIn = BytesLib.toAddress(data, 52);
  29 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 72);
  30 |     | /// @notice         uint256 minSharesOut = BytesLib.toUint256(data, 104);
  31 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 136);
  32 | *   | contract ApproveAndDeposit5115VaultHook is
  33 |     |     BaseHook,
  34 |     |     VaultBankLockableHook,
  35 |     |     ISuperHookInflowOutflow,
  36 |     |     ISuperHookContextAware
  37 |     | {
  38 |     |     using HookDataDecoder for bytes;
  39 |     | 
  40 | *   |     uint256 private constant AMOUNT_POSITION = 72;
  41 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 136;
  42 |     | 
  43 | *   |     constructor() BaseHook(HookType.INFLOW, HookSubTypes.ERC5115) { }
  44 |     | 
  45 |     |     /*//////////////////////////////////////////////////////////////
  46 |     |                                  VIEW METHODS
  47 |     |     //////////////////////////////////////////////////////////////*/
  48 |     |     /// @inheritdoc BaseHook
  49 | *   |     function _buildHookExecutions(
  50 |     |         address prevHook,
  51 |     |         address account,
  52 |     |         bytes calldata data
  53 |     |     )
  54 |     |         internal
  55 |     |         view
  56 |     |         override
  57 | *   |         returns (Execution[] memory executions)
  58 | *   |     {
  59 | *   |         address yieldSource = data.extractYieldSource();
  60 | *   |         address tokenIn = BytesLib.toAddress(data, 52);
  61 | *   |         uint256 amount = BytesLib.toUint256(data, AMOUNT_POSITION);
  62 | *   |         uint256 minSharesOut = BytesLib.toUint256(data, 104);
  63 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  64 |     | 
  65 | *   |         if (usePrevHookAmount) {
  66 | *   |             amount = ISuperHookResult(prevHook).getOutAmount(account);
  67 |     |         }
  68 |     | 
  69 | *   |         if (amount == 0) revert AMOUNT_NOT_VALID();
  70 | *   |         if (yieldSource == address(0) || account == address(0) || tokenIn == address(0)) revert ADDRESS_NOT_VALID();
  71 |     | 
  72 | *   |         executions = new Execution[](4);
  73 | *   |         executions[0] =
  74 | *   |             Execution({ target: tokenIn, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, 0)) });
  75 | *   |         executions[1] =
  76 | *   |             Execution({ target: tokenIn, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, amount)) });
  77 | *   |         executions[2] = Execution({
  78 | *   |             target: yieldSource,
  79 | *   |             value: 0,
  80 | *   |             callData: abi.encodeCall(IStandardizedYield.deposit, (account, tokenIn, amount, minSharesOut))
  81 |     |         });
  82 | *   |         executions[3] =
  83 | *   |             Execution({ target: tokenIn, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, 0)) });
  84 |     |     }
  85 |     | 
  86 |     |     /*//////////////////////////////////////////////////////////////
  87 |     |                                  EXTERNAL METHODS
  88 |     |     //////////////////////////////////////////////////////////////*/
  89 |     | 
  90 |     |     /// @inheritdoc ISuperHookInflowOutflow
  91 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  92 |     |         return _decodeAmount(data);
  93 |     |     }
  94 |     | 
  95 |     |     /// @inheritdoc ISuperHookContextAware
  96 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  97 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  98 |     |     }
  99 |     | 
 100 |     |     /// @inheritdoc ISuperHookInspector
 101 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
 102 | *   |         return abi.encodePacked(
 103 | *   |             data.extractYieldSource(),
 104 | *   |             BytesLib.toAddress(data, 52) // tokenIn
 105 |     |         );
 106 |     |     }
 107 |     | 
 108 |     |     /*//////////////////////////////////////////////////////////////
 109 |     |                                  INTERNAL METHODS
 110 |     |     //////////////////////////////////////////////////////////////*/
 111 | *   |     function _preExecute(address, address account, bytes calldata data) internal override {
 112 | *   |         _setOutAmount(_getBalance(account, data), account);
 113 | *   |         spToken = data.extractYieldSource();
 114 | *   |         asset = BytesLib.toAddress(data, 52);
 115 |     |     }
 116 |     | 
 117 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 118 | *   |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 119 |     |     }
 120 |     | 
 121 |     |     /*//////////////////////////////////////////////////////////////
 122 |     |                                  PRIVATE METHODS
 123 |     |     //////////////////////////////////////////////////////////////*/
 124 |     |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 125 |     |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 126 |     |     }
 127 |     | 
 128 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 129 | *   |         return IStandardizedYield(data.extractYieldSource()).balanceOf(account);
 130 |     |     }
 131 |     | }
 132 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/5115/Deposit5115VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IStandardizedYield } from "../../../vendor/pendle/IStandardizedYield.sol";
   8 |     | 
   9 |     | // Superform
  10 |     | import { BaseHook } from "../../BaseHook.sol";
  11 |     | import { VaultBankLockableHook } from "../../VaultBankLockableHook.sol";
  12 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  13 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  14 |     | import {
  15 |     |     ISuperHookResult,
  16 |     |     ISuperHookInflowOutflow,
  17 |     |     ISuperHookContextAware,
  18 |     |     ISuperHookInspector
  19 |     | } from "../../../interfaces/ISuperHook.sol";
  20 |     | 
  21 |     | /// @title Deposit5115VaultHook
  22 |     | /// @author Superform Labs
  23 |     | /// @dev data has the following structure
  24 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  25 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  26 |     | /// @notice         address tokenIn = BytesLib.toAddress(data, 52);
  27 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 72);
  28 |     | /// @notice         uint256 minSharesOut = BytesLib.toUint256(data, 104);
  29 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 136);
  30 | *   | contract Deposit5115VaultHook is BaseHook, VaultBankLockableHook, ISuperHookInflowOutflow, ISuperHookContextAware {
  31 |     |     using HookDataDecoder for bytes;
  32 |     | 
  33 | *   |     uint256 private constant AMOUNT_POSITION = 72;
  34 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 136;
  35 |     | 
  36 | *   |     constructor() BaseHook(HookType.INFLOW, HookSubTypes.ERC5115) { }
  37 |     | 
  38 |     |     /*//////////////////////////////////////////////////////////////
  39 |     |                                  VIEW METHODS
  40 |     |     //////////////////////////////////////////////////////////////*/
  41 |     |     /// @inheritdoc BaseHook
  42 | *   |     function _buildHookExecutions(
  43 |     |         address prevHook,
  44 |     |         address account,
  45 |     |         bytes calldata data
  46 |     |     )
  47 |     |         internal
  48 |     |         view
  49 |     |         override
  50 | *   |         returns (Execution[] memory executions)
  51 |     |     {
  52 | *   |         address yieldSource = data.extractYieldSource();
  53 | *   |         address tokenIn = BytesLib.toAddress(data, 52);
  54 | *   |         uint256 amount = BytesLib.toUint256(data, AMOUNT_POSITION);
  55 | *   |         uint256 minSharesOut = BytesLib.toUint256(data, 104);
  56 |     |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  57 |     | 
  58 |     |         if (usePrevHookAmount) {
  59 |     |             amount = ISuperHookResult(prevHook).getOutAmount(account);
  60 |     |         }
  61 |     | 
  62 |     |         if (amount == 0) revert AMOUNT_NOT_VALID();
  63 |     |         if (yieldSource == address(0) || account == address(0)) revert ADDRESS_NOT_VALID();
  64 |     | 
  65 |     |         executions = new Execution[](1);
  66 |     |         executions[0] = Execution({
  67 |     |             target: yieldSource,
  68 |     |             value: tokenIn == address(0) ? amount : 0,
  69 |     |             callData: abi.encodeCall(IStandardizedYield.deposit, (account, tokenIn, amount, minSharesOut))
  70 |     |         });
  71 |     |     }
  72 |     | 
  73 |     |     /*//////////////////////////////////////////////////////////////
  74 |     |                                  EXTERNAL METHODS
  75 |     |     //////////////////////////////////////////////////////////////*/
  76 |     | 
  77 |     |     /// @inheritdoc ISuperHookInflowOutflow
  78 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  79 |     |         return _decodeAmount(data);
  80 |     |     }
  81 |     | 
  82 |     |     /// @inheritdoc ISuperHookContextAware
  83 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  84 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  85 |     |     }
  86 |     | 
  87 |     |     /// @inheritdoc ISuperHookInspector
  88 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  89 | *   |         return abi.encodePacked(
  90 | *   |             data.extractYieldSource(),
  91 | *   |             BytesLib.toAddress(data, 52) // tokenIn
  92 |     |         );
  93 |     |     }
  94 |     | 
  95 |     |     /*//////////////////////////////////////////////////////////////
  96 |     |                                  INTERNAL METHODS
  97 |     |     //////////////////////////////////////////////////////////////*/
  98 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
  99 |     |         _setOutAmount(_getBalance(account, data), account);
 100 |     |         spToken = data.extractYieldSource();
 101 |     |         asset = BytesLib.toAddress(data, 52);
 102 |     |     }
 103 |     | 
 104 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 105 |     |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 106 |     |     }
 107 |     | 
 108 |     |     /*//////////////////////////////////////////////////////////////
 109 |     |                                  PRIVATE METHODS
 110 |     |     //////////////////////////////////////////////////////////////*/
 111 |     |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 112 |     |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 113 |     |     }
 114 |     | 
 115 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 116 | *   |         return IStandardizedYield(data.extractYieldSource()).balanceOf(account);
 117 |     |     }
 118 |     | }
 119 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/5115/Redeem5115VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   7 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   8 |     | import { IStandardizedYield } from "../../../vendor/pendle/IStandardizedYield.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import {
  13 |     |     ISuperHookResultOutflow,
  14 |     |     ISuperHookInflowOutflow,
  15 |     |     ISuperHookOutflow,
  16 |     |     ISuperHookContextAware,
  17 |     |     ISuperHookInspector
  18 |     | } from "../../../interfaces/ISuperHook.sol";
  19 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  20 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  21 |     | 
  22 |     | /// @title Redeem5115VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @dev data has the following structure
  25 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  26 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  27 |     | /// @notice         address tokenOut = BytesLib.toAddress(data, 52);
  28 |     | /// @notice         uint256 shares = BytesLib.toUint256(data, 72);
  29 |     | /// @notice         uint256 minTokenOut = BytesLib.toUint256(data, 104);
  30 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 136);
  31 | *   | contract Redeem5115VaultHook is BaseHook, ISuperHookInflowOutflow, ISuperHookOutflow, ISuperHookContextAware {
  32 |     |     using HookDataDecoder for bytes;
  33 |     | 
  34 | *   |     uint256 private constant AMOUNT_POSITION = 72;
  35 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 136;
  36 |     | 
  37 | *   |     constructor() BaseHook(HookType.OUTFLOW, HookSubTypes.ERC5115) { }
  38 |     | 
  39 |     |     /*//////////////////////////////////////////////////////////////
  40 |     |                                  VIEW METHODS
  41 |     |     //////////////////////////////////////////////////////////////*/
  42 |     |     /// @inheritdoc BaseHook
  43 | *   |     function _buildHookExecutions(
  44 |     |         address prevHook,
  45 |     |         address account,
  46 |     |         bytes calldata data
  47 |     |     )
  48 |     |         internal
  49 |     |         view
  50 |     |         override
  51 | *   |         returns (Execution[] memory executions)
  52 |     |     {
  53 | *   |         address yieldSource = data.extractYieldSource();
  54 | *   |         address tokenOut = BytesLib.toAddress(data, 52);
  55 | *   |         uint256 shares = _decodeAmount(data);
  56 | *   |         uint256 minTokenOut = BytesLib.toUint256(data, 104);
  57 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  58 |     | 
  59 | *   |         if (usePrevHookAmount) {
  60 | *   |             shares = ISuperHookResultOutflow(prevHook).getOutAmount(account);
  61 |     |         }
  62 |     | 
  63 |     |         if (shares == 0) revert AMOUNT_NOT_VALID();
  64 |     |         if (yieldSource == address(0) || tokenOut == address(0)) revert ADDRESS_NOT_VALID();
  65 |     | 
  66 |     |         executions = new Execution[](1);
  67 |     |         executions[0] = Execution({
  68 |     |             target: yieldSource,
  69 |     |             value: 0,
  70 |     |             callData: abi.encodeCall(IStandardizedYield.redeem, (account, shares, tokenOut, minTokenOut, false))
  71 |     |         });
  72 |     |     }
  73 |     | 
  74 |     |     /*//////////////////////////////////////////////////////////////
  75 |     |                                  EXTERNAL METHODS
  76 |     |     //////////////////////////////////////////////////////////////*/
  77 |     | 
  78 |     |     /// @inheritdoc ISuperHookInflowOutflow
  79 | *   |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  80 | *   |         return _decodeAmount(data);
  81 |     |     }
  82 |     | 
  83 |     |     /// @inheritdoc ISuperHookContextAware
  84 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  85 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  86 |     |     }
  87 |     | 
  88 |     |     /// @inheritdoc ISuperHookOutflow
  89 | *   |     function replaceCalldataAmount(bytes memory data, uint256 amount) external pure returns (bytes memory) {
  90 | *   |         return _replaceCalldataAmount(data, amount, AMOUNT_POSITION);
  91 |     |     }
  92 |     | 
  93 |     |     /// @inheritdoc ISuperHookInspector
  94 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  95 | *   |         return abi.encodePacked(
  96 | *   |             data.extractYieldSource(),
  97 | *   |             BytesLib.toAddress(data, 52) // tokenOut
  98 |     |         );
  99 |     |     }
 100 |     | 
 101 |     |     /*//////////////////////////////////////////////////////////////
 102 |     |                                  INTERNAL METHODS
 103 |     |     //////////////////////////////////////////////////////////////*/
 104 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
 105 |     |         asset = BytesLib.toAddress(data, 52); // tokenOut from data
 106 |     |         _setOutAmount(_getBalance(account, data), account);
 107 |     |         usedShares = _getSharesBalance(account, data);
 108 |     |         spToken = data.extractYieldSource();
 109 |     |     }
 110 |     | 
 111 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 112 |     |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 113 |     |         usedShares = usedShares - _getSharesBalance(account, data);
 114 |     |     }
 115 |     | 
 116 |     |     /*//////////////////////////////////////////////////////////////
 117 |     |                                  PRIVATE METHODS
 118 |     |     //////////////////////////////////////////////////////////////*/
 119 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 120 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 121 |     |     }
 122 |     | 
 123 |     |     function _getBalance(address account, bytes memory) private view returns (uint256) {
 124 |     |         return IERC20(asset).balanceOf(account);
 125 |     |     }
 126 |     | 
 127 | *   |     function _getSharesBalance(address account, bytes memory data) private view returns (uint256) {
 128 |     |         address yieldSource = data.extractYieldSource();
 129 | *   |         return IStandardizedYield(yieldSource).balanceOf(account);
 130 |     |     }
 131 |     | }
 132 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/ApproveAndRequestDeposit7540VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
   7 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   8 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import {
  12 |     |     ISuperHookResult,
  13 |     |     ISuperHookInflowOutflow,
  14 |     |     ISuperHookContextAware,
  15 |     |     ISuperHookInspector
  16 |     | } from "../../../interfaces/ISuperHook.sol";
  17 |     | import { BaseHook } from "../../BaseHook.sol";
  18 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  19 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  20 |     | 
  21 |     | /// @title ApproveAndRequestDeposit7540VaultHook
  22 |     | /// @author Superform Labs
  23 |     | /// @notice This hook does not support tokens reverting on 0 approval
  24 |     | /// @dev data has the following structure
  25 |     | /// @notice         bytes32 placeholder = bytes32(BytesLib.slice(data, 0, 32), 0);
  26 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  27 |     | /// @notice         address token = BytesLib.toAddress(data, 52);
  28 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 72);
  29 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 104);
  30 | *   | contract ApproveAndRequestDeposit7540VaultHook is BaseHook, ISuperHookInflowOutflow, ISuperHookContextAware {
  31 |     |     using HookDataDecoder for bytes;
  32 |     | 
  33 | *   |     uint256 private constant AMOUNT_POSITION = 72;
  34 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 104;
  35 |     | 
  36 | *   |     constructor() BaseHook(HookType.NONACCOUNTING, HookSubTypes.ERC7540) { }
  37 |     | 
  38 |     |     /*//////////////////////////////////////////////////////////////
  39 |     |                                  VIEW METHODS
  40 |     |     //////////////////////////////////////////////////////////////*/
  41 |     |     /// @inheritdoc BaseHook
  42 | *   |     function _buildHookExecutions(
  43 |     |         address prevHook,
  44 |     |         address account,
  45 |     |         bytes calldata data
  46 |     |     )
  47 |     |         internal
  48 |     |         view
  49 |     |         override
  50 | *   |         returns (Execution[] memory executions)
  51 |     |     {
  52 | *   |         address yieldSource = data.extractYieldSource();
  53 | *   |         address token = BytesLib.toAddress(data, 52);
  54 | *   |         uint256 amount = _decodeAmount(data);
  55 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  56 |     | 
  57 | *   |         if (usePrevHookAmount) {
  58 | *   |             amount = ISuperHookResult(prevHook).getOutAmount(account);
  59 |     |         }
  60 |     | 
  61 |     |         if (amount == 0) revert AMOUNT_NOT_VALID();
  62 |     |         if (yieldSource == address(0) || account == address(0) || token == address(0)) revert ADDRESS_NOT_VALID();
  63 |     | 
  64 |     |         executions = new Execution[](4);
  65 |     |         executions[0] =
  66 |     |             Execution({ target: token, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, 0)) });
  67 |     |         executions[1] =
  68 |     |             Execution({ target: token, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, amount)) });
  69 |     |         executions[2] = Execution({
  70 |     |             target: yieldSource,
  71 |     |             value: 0,
  72 |     |             callData: abi.encodeCall(IERC7540.requestDeposit, (amount, account, account))
  73 |     |         });
  74 |     |         executions[3] =
  75 |     |             Execution({ target: token, value: 0, callData: abi.encodeCall(IERC20.approve, (yieldSource, 0)) });
  76 |     |     }
  77 |     | 
  78 |     |     /*//////////////////////////////////////////////////////////////
  79 |     |                                  EXTERNAL METHODS
  80 |     |     //////////////////////////////////////////////////////////////*/
  81 |     | 
  82 |     |     /// @inheritdoc ISuperHookInflowOutflow
  83 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  84 |     |         return _decodeAmount(data);
  85 |     |     }
  86 |     | 
  87 |     |     /// @inheritdoc ISuperHookContextAware
  88 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  89 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  90 |     |     }
  91 |     | 
  92 |     |     /// @inheritdoc ISuperHookInspector
  93 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  94 | *   |         return abi.encodePacked(
  95 | *   |             data.extractYieldSource(),
  96 | *   |             BytesLib.toAddress(data, 52) //token
  97 |     |         );
  98 |     |     }
  99 |     | 
 100 |     |     /*//////////////////////////////////////////////////////////////    
 101 |     |                                  INTERNAL METHODS
 102 |     |     //////////////////////////////////////////////////////////////*/
 103 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
 104 |     |         _setOutAmount(_getBalance(account, data), account);
 105 |     |     }
 106 |     | 
 107 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 108 |     |         _setOutAmount(getOutAmount(account) - _getBalance(account, data), account);
 109 |     |     }
 110 |     | 
 111 |     |     /*//////////////////////////////////////////////////////////////
 112 |     |                                  PRIVATE METHODS
 113 |     |     //////////////////////////////////////////////////////////////*/
 114 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 115 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 116 |     |     }
 117 |     | 
 118 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 119 | *   |         return IERC20(IERC7540(data.extractYieldSource()).asset()).balanceOf(account);
 120 |     |     }
 121 |     | }
 122 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/CancelDepositRequest7540Hook.sol
  1 |     | // SPDX-License-Identifier: Apache-2.0
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | // external
  5 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
  6 |     | import { IERC7540CancelDeposit } from "../../../vendor/standards/ERC7540/IERC7540Vault.sol";
  7 |     | 
  8 |     | // Superform
  9 |     | import { BaseHook } from "../../BaseHook.sol";
 10 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
 11 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
 12 |     | import { ISuperHookInspector } from "../../../interfaces/ISuperHook.sol";
 13 |     | 
 14 |     | /// @title CancelDepositRequest7540Hook
 15 |     | /// @author Superform Labs
 16 |     | /// @dev data has the following structure
 17 |     | /// @notice         bytes32 placeholder = bytes32(BytesLib.slice(data, 0, 32), 0);
 18 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
 19 | *   | contract CancelDepositRequest7540Hook is BaseHook {
 20 |     |     using HookDataDecoder for bytes;
 21 |     | 
 22 | *   |     constructor() BaseHook(HookType.NONACCOUNTING, HookSubTypes.CANCEL_DEPOSIT_REQUEST) { }
 23 |     | 
 24 |     |     /*//////////////////////////////////////////////////////////////
 25 |     |                                  VIEW METHODS
 26 |     |     //////////////////////////////////////////////////////////////*/
 27 |     |     /// @inheritdoc BaseHook
 28 | *   |     function _buildHookExecutions(
 29 |     |         address,
 30 |     |         address account,
 31 |     |         bytes calldata data
 32 |     |     )
 33 |     |         internal
 34 |     |         pure
 35 |     |         override
 36 | *   |         returns (Execution[] memory executions)
 37 |     |     {
 38 | *   |         address yieldSource = data.extractYieldSource();
 39 |     | 
 40 | *   |         if (yieldSource == address(0)) revert ADDRESS_NOT_VALID();
 41 |     | 
 42 | *   |         executions = new Execution[](1);
 43 | *   |         executions[0] = Execution({
 44 | *   |             target: yieldSource,
 45 | *   |             value: 0,
 46 | *   |             callData: abi.encodeCall(IERC7540CancelDeposit.cancelDepositRequest, (0, account))
 47 |     |         });
 48 |     |     }
 49 |     | 
 50 |     |     /// @inheritdoc ISuperHookInspector
 51 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
 52 | *   |         return abi.encodePacked(data.extractYieldSource());
 53 |     |     }
 54 |     | }
 55 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/CancelRedeemRequest7540Hook.sol
  1 |     | // SPDX-License-Identifier: Apache-2.0
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | // external
  5 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
  6 |     | import { IERC7540CancelRedeem } from "../../../vendor/standards/ERC7540/IERC7540Vault.sol";
  7 |     | 
  8 |     | // Superform
  9 |     | import { BaseHook } from "../../BaseHook.sol";
 10 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
 11 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
 12 |     | import { ISuperHookInspector } from "../../../interfaces/ISuperHook.sol";
 13 |     | 
 14 |     | /// @title CancelRedeemRequest7540Hook
 15 |     | /// @author Superform Labs
 16 |     | /// @dev data has the following structure
 17 |     | /// @notice         bytes32 placeholder = bytes32(BytesLib.slice(data, 0, 32), 0);
 18 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
 19 | *   | contract CancelRedeemRequest7540Hook is BaseHook {
 20 |     |     using HookDataDecoder for bytes;
 21 |     | 
 22 | *   |     constructor() BaseHook(HookType.NONACCOUNTING, HookSubTypes.CANCEL_REDEEM_REQUEST) { }
 23 |     | 
 24 |     |     /*//////////////////////////////////////////////////////////////
 25 |     |                                  VIEW METHODS
 26 |     |     //////////////////////////////////////////////////////////////*/
 27 |     |     /// @inheritdoc BaseHook
 28 | *   |     function _buildHookExecutions(
 29 |     |         address,
 30 |     |         address account,
 31 |     |         bytes calldata data
 32 |     |     )
 33 |     |         internal
 34 |     |         pure
 35 |     |         override
 36 | *   |         returns (Execution[] memory executions)
 37 |     |     {
 38 | *   |         address yieldSource = data.extractYieldSource();
 39 |     | 
 40 | *   |         if (yieldSource == address(0)) revert ADDRESS_NOT_VALID();
 41 |     | 
 42 | *   |         executions = new Execution[](1);
 43 | *   |         executions[0] = Execution({
 44 | *   |             target: yieldSource,
 45 | *   |             value: 0,
 46 | *   |             callData: abi.encodeCall(IERC7540CancelRedeem.cancelRedeemRequest, (0, account))
 47 |     |         });
 48 |     |     }
 49 |     | 
 50 |     |     /// @inheritdoc ISuperHookInspector
 51 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
 52 | *   |         return abi.encodePacked(data.extractYieldSource());
 53 |     |     }
 54 |     | }
 55 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/ClaimCancelDepositRequest7540Hook.sol
  1 |     | // SPDX-License-Identifier: Apache-2.0
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | // external
  5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
  6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
  7 |     | import { IERC7540CancelDeposit } from "../../../vendor/standards/ERC7540/IERC7540Vault.sol";
  8 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
  9 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
 10 |     | 
 11 |     | // Superform
 12 |     | import { BaseHook } from "../../BaseHook.sol";
 13 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
 14 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
 15 |     | import { ISuperHookAsyncCancelations, ISuperHookInspector } from "../../../interfaces/ISuperHook.sol";
 16 |     | 
 17 |     | /// @title ClaimCancelDepositRequest7540Hook
 18 |     | /// @author Superform Labs
 19 |     | /// @dev data has the following structure
 20 |     | /// @notice         bytes32 placeholder = bytes32(BytesLib.slice(data, 0, 32), 0);
 21 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
 22 |     | /// @notice         address receiver = BytesLib.toAddress(data, 52);
 23 | *   | contract ClaimCancelDepositRequest7540Hook is BaseHook, ISuperHookAsyncCancelations {
 24 |     |     using HookDataDecoder for bytes;
 25 |     | 
 26 | *   |     constructor() BaseHook(HookType.NONACCOUNTING, HookSubTypes.CLAIM_CANCEL_DEPOSIT_REQUEST) { }
 27 |     | 
 28 |     |     /*//////////////////////////////////////////////////////////////
 29 |     |                                  VIEW METHODS
 30 |     |     //////////////////////////////////////////////////////////////*/
 31 |     |     /// @inheritdoc BaseHook
 32 | *   |     function _buildHookExecutions(
 33 |     |         address,
 34 |     |         address account,
 35 |     |         bytes calldata data
 36 |     |     )
 37 |     |         internal
 38 |     |         pure
 39 |     |         override
 40 | *   |         returns (Execution[] memory executions)
 41 | *   |     {
 42 | *   |         address yieldSource = data.extractYieldSource();
 43 | *   |         address receiver = BytesLib.toAddress(data, 52);
 44 |     | 
 45 | *   |         if (yieldSource == address(0) || receiver == address(0)) revert ADDRESS_NOT_VALID();
 46 |     | 
 47 | *   |         executions = new Execution[](1);
 48 | *   |         executions[0] = Execution({
 49 | *   |             target: yieldSource,
 50 | *   |             value: 0,
 51 | *   |             callData: abi.encodeCall(IERC7540CancelDeposit.claimCancelDepositRequest, (0, receiver, account))
 52 |     |         });
 53 |     |     }
 54 |     | 
 55 |     |     /*//////////////////////////////////////////////////////////////
 56 |     |                                  EXTERNAL METHODS
 57 |     |     //////////////////////////////////////////////////////////////*/
 58 |     | 
 59 |     |     /// @inheritdoc ISuperHookAsyncCancelations
 60 |     |     function isAsyncCancelHook() external pure returns (CancelationType) {
 61 |     |         return CancelationType.INFLOW;
 62 |     |     }
 63 |     | 
 64 |     |     /// @inheritdoc ISuperHookInspector
 65 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
 66 | *   |         return abi.encodePacked(
 67 | *   |             data.extractYieldSource(),
 68 | *   |             BytesLib.toAddress(data, 52) //receiver
 69 |     |         );
 70 |     |     }
 71 |     | 
 72 |     |     /*//////////////////////////////////////////////////////////////
 73 |     |                                  INTERNAL METHODS
 74 |     |     //////////////////////////////////////////////////////////////*/
 75 | *   |     function _preExecute(address, address account, bytes calldata data) internal override {
 76 | *   |         address yieldSource = data.extractYieldSource();
 77 | *   |         address receiver = BytesLib.toAddress(data, 52);
 78 | *   |         asset = IERC7540(yieldSource).asset();
 79 |     |         // store current balance
 80 | *   |         _setOutAmount(_getBalance(receiver, data), account);
 81 |     |     }
 82 |     | 
 83 | *   |     function _postExecute(address, address account, bytes calldata data) internal override {
 84 | *   |         address receiver = BytesLib.toAddress(data, 52);
 85 |     | 
 86 | *   |         _setOutAmount(_getBalance(receiver, data) - getOutAmount(account), account);
 87 |     |     }
 88 |     | 
 89 |     |     /*//////////////////////////////////////////////////////////////
 90 |     |                                  PRIVATE METHODS
 91 |     |     //////////////////////////////////////////////////////////////*/
 92 |     | 
 93 | *   |     function _getBalance(address account, bytes memory) private view returns (uint256) {
 94 | *   |         return IERC20(asset).balanceOf(account);
 95 |     |     }
 96 |     | }
 97 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/ClaimCancelRedeemRequest7540Hook.sol
  1 |     | // SPDX-License-Identifier: Apache-2.0
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | // external
  5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
  6 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
  7 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
  8 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
  9 |     | import { IERC7540CancelRedeem } from "../../../vendor/standards/ERC7540/IERC7540Vault.sol";
 10 |     | 
 11 |     | // Superform
 12 |     | import { BaseHook } from "../../BaseHook.sol";
 13 |     | import { VaultBankLockableHook } from "../../VaultBankLockableHook.sol";
 14 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
 15 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
 16 |     | import { ISuperHookAsyncCancelations, ISuperHookInspector } from "../../../interfaces/ISuperHook.sol";
 17 |     | 
 18 |     | /// @title ClaimCancelRedeemRequest7540Hook
 19 |     | /// @author Superform Labs
 20 |     | /// @dev data has the following structure
 21 |     | /// @notice         bytes32 placeholder = bytes32(BytesLib.slice(data, 0, 32), 0);
 22 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
 23 |     | /// @notice         address receiver = BytesLib.toAddress(data, 52);
 24 | *   | contract ClaimCancelRedeemRequest7540Hook is BaseHook, VaultBankLockableHook, ISuperHookAsyncCancelations {
 25 |     |     using HookDataDecoder for bytes;
 26 |     | 
 27 | *   |     constructor() BaseHook(HookType.NONACCOUNTING, HookSubTypes.CLAIM_CANCEL_REDEEM_REQUEST) { }
 28 |     | 
 29 |     |     /*//////////////////////////////////////////////////////////////
 30 |     |                                  VIEW METHODS
 31 |     |     //////////////////////////////////////////////////////////////*/
 32 |     |     /// @inheritdoc BaseHook
 33 | *   |     function _buildHookExecutions(
 34 |     |         address,
 35 |     |         address account,
 36 |     |         bytes calldata data
 37 |     |     )
 38 |     |         internal
 39 |     |         pure
 40 |     |         override
 41 | *   |         returns (Execution[] memory executions)
 42 | *   |     {
 43 | *   |         address yieldSource = data.extractYieldSource();
 44 | *   |         address receiver = BytesLib.toAddress(data, 52);
 45 |     | 
 46 | *   |         if (yieldSource == address(0) || receiver == address(0)) revert ADDRESS_NOT_VALID();
 47 |     | 
 48 | *   |         executions = new Execution[](1);
 49 | *   |         executions[0] = Execution({
 50 | *   |             target: yieldSource,
 51 | *   |             value: 0,
 52 | *   |             callData: abi.encodeCall(IERC7540CancelRedeem.claimCancelRedeemRequest, (0, receiver, account))
 53 |     |         });
 54 |     |     }
 55 |     | 
 56 |     |     /*//////////////////////////////////////////////////////////////
 57 |     |                                  EXTERNAL METHODS
 58 |     |     //////////////////////////////////////////////////////////////*/
 59 |     | 
 60 |     |     /// @inheritdoc ISuperHookAsyncCancelations
 61 |     |     function isAsyncCancelHook() external pure returns (CancelationType) {
 62 |     |         return CancelationType.OUTFLOW;
 63 |     |     }
 64 |     | 
 65 |     |     /// @inheritdoc ISuperHookInspector
 66 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
 67 | *   |         return abi.encodePacked(
 68 | *   |             data.extractYieldSource(),
 69 | *   |             BytesLib.toAddress(data, 52) //receiver
 70 |     |         );
 71 |     |     }
 72 |     | 
 73 |     |     /*//////////////////////////////////////////////////////////////
 74 |     |                                  INTERNAL METHODS
 75 |     |     //////////////////////////////////////////////////////////////*/
 76 | *   |     function _preExecute(address, address account, bytes calldata data) internal override {
 77 | *   |         _setOutAmount(_getBalance(account, data), account);
 78 | *   |         spToken = IERC7540(data.extractYieldSource()).share();
 79 |     |     }
 80 |     | 
 81 | *   |     function _postExecute(address, address account, bytes calldata data) internal override {
 82 | *   |         address receiver = BytesLib.toAddress(data, 52);
 83 | *   |         _setOutAmount(_getBalance(receiver, data) - getOutAmount(account), account);
 84 |     |     }
 85 |     | 
 86 |     |     /*//////////////////////////////////////////////////////////////
 87 |     |                                  PRIVATE METHODS
 88 |     |     //////////////////////////////////////////////////////////////*/
 89 |     | 
 90 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 91 | *   |         return IERC20(IERC7540(data.extractYieldSource()).share()).balanceOf(account);
 92 |     |     }
 93 |     | }
 94 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/Deposit7540VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
   8 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import { VaultBankLockableHook } from "../../VaultBankLockableHook.sol";
  13 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  14 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  15 |     | import {
  16 |     |     ISuperHookResult,
  17 |     |     ISuperHookInflowOutflow,
  18 |     |     ISuperHookContextAware,
  19 |     |     ISuperHookInspector
  20 |     | } from "../../../interfaces/ISuperHook.sol";
  21 |     | 
  22 |     | /// @title Deposit7540VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @dev data has the following structure
  25 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  26 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  27 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 52);
  28 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 84);
  29 | *   | contract Deposit7540VaultHook is BaseHook, VaultBankLockableHook, ISuperHookInflowOutflow, ISuperHookContextAware {
  30 |     |     using HookDataDecoder for bytes;
  31 |     | 
  32 | *   |     uint256 private constant AMOUNT_POSITION = 52;
  33 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 84;
  34 |     | 
  35 | *   |     constructor() BaseHook(HookType.INFLOW, HookSubTypes.ERC7540) { }
  36 |     | 
  37 |     |     /*//////////////////////////////////////////////////////////////
  38 |     |                                  VIEW METHODS
  39 |     |     //////////////////////////////////////////////////////////////*/
  40 |     |     /// @inheritdoc BaseHook
  41 | *   |     function _buildHookExecutions(
  42 |     |         address prevHook,
  43 |     |         address account,
  44 |     |         bytes calldata data
  45 |     |     )
  46 |     |         internal
  47 |     |         view
  48 |     |         override
  49 | *   |         returns (Execution[] memory executions)
  50 |     |     {
  51 | *   |         address yieldSource = data.extractYieldSource();
  52 | *   |         uint256 amount = _decodeAmount(data);
  53 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  54 |     | 
  55 | *   |         if (usePrevHookAmount) {
  56 | *   |             amount = ISuperHookResult(prevHook).getOutAmount(account);
  57 |     |         }
  58 |     | 
  59 |     |         if (amount == 0) revert AMOUNT_NOT_VALID();
  60 |     |         if (yieldSource == address(0) || account == address(0)) revert ADDRESS_NOT_VALID();
  61 |     | 
  62 |     |         executions = new Execution[](1);
  63 |     |         executions[0] = Execution({
  64 |     |             target: yieldSource,
  65 |     |             value: 0,
  66 |     |             callData: abi.encodeCall(IERC7540.deposit, (amount, account, account))
  67 |     |         });
  68 |     |     }
  69 |     | 
  70 |     |     /*//////////////////////////////////////////////////////////////
  71 |     |                                  EXTERNAL METHODS
  72 |     |     //////////////////////////////////////////////////////////////*/
  73 |     | 
  74 |     |     /// @inheritdoc ISuperHookInflowOutflow
  75 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  76 |     |         return _decodeAmount(data);
  77 |     |     }
  78 |     | 
  79 |     |     /// @inheritdoc ISuperHookContextAware
  80 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  81 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  82 |     |     }
  83 |     | 
  84 |     |     /// @inheritdoc ISuperHookInspector
  85 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  86 | *   |         return abi.encodePacked(data.extractYieldSource());
  87 |     |     }
  88 |     | 
  89 |     |     /*//////////////////////////////////////////////////////////////
  90 |     |                                  INTERNAL METHODS
  91 |     |     //////////////////////////////////////////////////////////////*/
  92 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
  93 |     |         // store current balance
  94 |     |         _setOutAmount(_getBalance(account, data), account);
  95 |     |         spToken = IERC7540(data.extractYieldSource()).share();
  96 |     |     }
  97 |     | 
  98 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
  99 |     |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 100 |     |     }
 101 |     | 
 102 |     |     /*//////////////////////////////////////////////////////////////
 103 |     |                                  PRIVATE METHODS
 104 |     |     //////////////////////////////////////////////////////////////*/
 105 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 106 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 107 |     |     }
 108 |     | 
 109 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 110 | *   |         return IERC20(IERC7540(data.extractYieldSource()).share()).balanceOf(account);
 111 |     |     }
 112 |     | }
 113 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/Redeem7540VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
   8 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import {
  13 |     |     ISuperHookResultOutflow,
  14 |     |     ISuperHookInflowOutflow,
  15 |     |     ISuperHookOutflow,
  16 |     |     ISuperHookContextAware,
  17 |     |     ISuperHookInspector
  18 |     | } from "../../../interfaces/ISuperHook.sol";
  19 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  20 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  21 |     | 
  22 |     | /// @title Redeem7540VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @notice This hook does not support tokens reverting on 0 approval
  25 |     | /// @dev data has the following structure
  26 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  27 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  28 |     | /// @notice         uint256 shares = BytesLib.toUint256(data, 52);
  29 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 84);
  30 | *   | contract Redeem7540VaultHook is BaseHook, ISuperHookInflowOutflow, ISuperHookOutflow, ISuperHookContextAware {
  31 |     |     using HookDataDecoder for bytes;
  32 |     | 
  33 | *   |     uint256 private constant AMOUNT_POSITION = 52;
  34 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 84;
  35 |     | 
  36 | *   |     constructor() BaseHook(HookType.OUTFLOW, HookSubTypes.ERC7540) { }
  37 |     | 
  38 |     |     /*//////////////////////////////////////////////////////////////
  39 |     |                                  VIEW METHODS
  40 |     |     //////////////////////////////////////////////////////////////*/
  41 |     |     /// @inheritdoc BaseHook
  42 | *   |     function _buildHookExecutions(
  43 |     |         address prevHook,
  44 |     |         address account,
  45 |     |         bytes calldata data
  46 |     |     )
  47 |     |         internal
  48 |     |         view
  49 |     |         override
  50 | *   |         returns (Execution[] memory executions)
  51 | *   |     {
  52 | *   |         address yieldSource = data.extractYieldSource();
  53 | *   |         uint256 shares = _decodeAmount(data);
  54 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  55 |     | 
  56 | *   |         if (usePrevHookAmount) {
  57 | *   |             shares = ISuperHookResultOutflow(prevHook).getOutAmount(account);
  58 |     |         }
  59 |     | 
  60 | *   |         if (shares == 0) revert AMOUNT_NOT_VALID();
  61 | *   |         if (yieldSource == address(0) || account == address(0)) revert ADDRESS_NOT_VALID();
  62 |     | 
  63 | *   |         executions = new Execution[](1);
  64 | *   |         executions[0] = Execution({
  65 |     |             target: yieldSource,
  66 |     |             value: 0,
  67 | *   |             callData: abi.encodeCall(IERC7540.redeem, (shares, account, account))
  68 |     |         });
  69 |     |     }
  70 |     | 
  71 |     |     /*//////////////////////////////////////////////////////////////
  72 |     |                                  EXTERNAL METHODS
  73 |     |     //////////////////////////////////////////////////////////////*/
  74 |     |     /// @inheritdoc ISuperHookInflowOutflow
  75 | *   |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  76 | *   |         return _decodeAmount(data);
  77 |     |     }
  78 |     | 
  79 |     |     /// @inheritdoc ISuperHookContextAware
  80 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  81 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  82 |     |     }
  83 |     | 
  84 |     |     /// @inheritdoc ISuperHookOutflow
  85 | *   |     function replaceCalldataAmount(bytes memory data, uint256 amount) external pure returns (bytes memory) {
  86 | *   |         return _replaceCalldataAmount(data, amount, AMOUNT_POSITION);
  87 |     |     }
  88 |     | 
  89 |     |     /// @inheritdoc ISuperHookInspector
  90 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  91 | *   |         return abi.encodePacked(data.extractYieldSource());
  92 |     |     }
  93 |     | 
  94 |     |     /*//////////////////////////////////////////////////////////////    
  95 |     |                                  INTERNAL METHODS
  96 |     |     //////////////////////////////////////////////////////////////*/
  97 | *   |     function _preExecute(address, address account, bytes calldata data) internal override {
  98 | *   |         address yieldSource = data.extractYieldSource();
  99 | *   |         asset = IERC7540(yieldSource).asset();
 100 | *   |         _setOutAmount(_getBalance(account, data), account);
 101 | *   |         usedShares = _getSharesBalance(account, data);
 102 | *   |         spToken = IERC7540(yieldSource).share();
 103 |     |     }
 104 |     | 
 105 | *   |     function _postExecute(address, address account, bytes calldata data) internal override {
 106 | *   |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 107 | *   |         usedShares = usedShares - _getSharesBalance(account, data);
 108 |     |     }
 109 |     | 
 110 |     |     /*//////////////////////////////////////////////////////////////
 111 |     |                                  PRIVATE METHODS
 112 |     |     //////////////////////////////////////////////////////////////*/
 113 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 114 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 115 |     |     }
 116 |     | 
 117 | *   |     function _getBalance(address account, bytes memory) private view returns (uint256) {
 118 | *   |         return IERC20(asset).balanceOf(account);
 119 |     |     }
 120 |     | 
 121 | *   |     function _getSharesBalance(address account, bytes memory data) private view returns (uint256) {
 122 | *   |         address yieldSource = data.extractYieldSource();
 123 | *   |         return IERC7540(yieldSource).claimableRedeemRequest(0, account);
 124 |     |     }
 125 |     | }
 126 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/RequestDeposit7540VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
   8 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import {
  13 |     |     ISuperHookResult,
  14 |     |     ISuperHookInflowOutflow,
  15 |     |     ISuperHookAsyncCancelations,
  16 |     |     ISuperHookContextAware,
  17 |     |     ISuperHookInspector
  18 |     | } from "../../../interfaces/ISuperHook.sol";
  19 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  20 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  21 |     | 
  22 |     | /// @title RequestDeposit7540VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @dev data has the following structure
  25 |     | /// @notice         bytes32 placeholder = bytes32(BytesLib.slice(data, 0, 32), 0);
  26 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  27 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 52);
  28 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 84);
  29 | *   | contract RequestDeposit7540VaultHook is
  30 |     |     BaseHook,
  31 |     |     ISuperHookInflowOutflow,
  32 |     |     ISuperHookAsyncCancelations,
  33 |     |     ISuperHookContextAware
  34 |     | {
  35 |     |     using HookDataDecoder for bytes;
  36 |     | 
  37 | *   |     uint256 private constant AMOUNT_POSITION = 52;
  38 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 84;
  39 |     | 
  40 | *   |     constructor() BaseHook(HookType.NONACCOUNTING, HookSubTypes.ERC7540) { }
  41 |     | 
  42 |     |     /*//////////////////////////////////////////////////////////////
  43 |     |                                  VIEW METHODS
  44 |     |     //////////////////////////////////////////////////////////////*/
  45 |     |     /// @inheritdoc BaseHook
  46 | *   |     function _buildHookExecutions(
  47 |     |         address prevHook,
  48 |     |         address account,
  49 |     |         bytes calldata data
  50 |     |     )
  51 |     |         internal
  52 |     |         view
  53 |     |         override
  54 | *   |         returns (Execution[] memory executions)
  55 |     |     {
  56 | *   |         address yieldSource = data.extractYieldSource();
  57 | *   |         uint256 amount = _decodeAmount(data);
  58 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  59 |     | 
  60 | *   |         if (usePrevHookAmount) {
  61 | *   |             amount = ISuperHookResult(prevHook).getOutAmount(account);
  62 |     |         }
  63 |     | 
  64 |     |         if (amount == 0) revert AMOUNT_NOT_VALID();
  65 |     |         if (yieldSource == address(0) || account == address(0)) revert ADDRESS_NOT_VALID();
  66 |     | 
  67 |     |         executions = new Execution[](1);
  68 |     |         executions[0] = Execution({
  69 |     |             target: yieldSource,
  70 |     |             value: 0,
  71 |     |             callData: abi.encodeCall(IERC7540.requestDeposit, (amount, account, account))
  72 |     |         });
  73 |     |     }
  74 |     | 
  75 |     |     /// @inheritdoc ISuperHookAsyncCancelations
  76 |     |     function isAsyncCancelHook() external pure returns (CancelationType) {
  77 |     |         return CancelationType.NONE;
  78 |     |     }
  79 |     | 
  80 |     |     /*//////////////////////////////////////////////////////////////
  81 |     |                                  EXTERNAL METHODS
  82 |     |     //////////////////////////////////////////////////////////////*/
  83 |     | 
  84 |     |     /// @inheritdoc ISuperHookInflowOutflow
  85 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  86 |     |         return _decodeAmount(data);
  87 |     |     }
  88 |     | 
  89 |     |     /// @inheritdoc ISuperHookContextAware
  90 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  91 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  92 |     |     }
  93 |     | 
  94 |     |     /// @inheritdoc ISuperHookInspector
  95 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  96 | *   |         return abi.encodePacked(data.extractYieldSource());
  97 |     |     }
  98 |     | 
  99 |     |     /*//////////////////////////////////////////////////////////////
 100 |     |                                  INTERNAL METHODS
 101 |     |     //////////////////////////////////////////////////////////////*/
 102 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
 103 |     |         _setOutAmount(_getBalance(account, data), account);
 104 |     |     }
 105 |     | 
 106 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 107 |     |         _setOutAmount(getOutAmount(account) - _getBalance(account, data), account);
 108 |     |     }
 109 |     | 
 110 |     |     /*//////////////////////////////////////////////////////////////
 111 |     |                                  PRIVATE METHODS
 112 |     |     //////////////////////////////////////////////////////////////*/
 113 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 114 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 115 |     |     }
 116 |     | 
 117 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 118 | *   |         return IERC20(IERC7540(data.extractYieldSource()).asset()).balanceOf(account);
 119 |     |     }
 120 |     | }
 121 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/RequestRedeem7540VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
   8 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   9 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
  10 |     | 
  11 |     | // Superform
  12 |     | import { BaseHook } from "../../BaseHook.sol";
  13 |     | import {
  14 |     |     ISuperHookResult,
  15 |     |     ISuperHookInflowOutflow,
  16 |     |     ISuperHookAsyncCancelations,
  17 |     |     ISuperHookContextAware,
  18 |     |     ISuperHookInspector
  19 |     | } from "../../../interfaces/ISuperHook.sol";
  20 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  21 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  22 |     | 
  23 |     | /// @title RequestRedeem7540VaultHook
  24 |     | /// @author Superform Labs
  25 |     | /// @dev data has the following structure
  26 |     | /// @notice         bytes32 placeholder = bytes32(BytesLib.slice(data, 0, 32), 0);
  27 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  28 |     | /// @notice         uint256 shares = BytesLib.toUint256(data, 52);
  29 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 84);
  30 | *   | contract RequestRedeem7540VaultHook is
  31 |     |     BaseHook,
  32 |     |     ISuperHookInflowOutflow,
  33 |     |     ISuperHookAsyncCancelations,
  34 |     |     ISuperHookContextAware
  35 |     | {
  36 |     |     using HookDataDecoder for bytes;
  37 |     | 
  38 | *   |     uint256 private constant AMOUNT_POSITION = 52;
  39 | *   |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 84;
  40 |     | 
  41 | *   |     constructor() BaseHook(HookType.NONACCOUNTING, HookSubTypes.ERC7540) { }
  42 |     | 
  43 |     |     /*//////////////////////////////////////////////////////////////
  44 |     |                                  VIEW METHODS
  45 |     |     //////////////////////////////////////////////////////////////*/
  46 |     |     /// @inheritdoc BaseHook
  47 | *   |     function _buildHookExecutions(
  48 |     |         address prevHook,
  49 |     |         address account,
  50 |     |         bytes calldata data
  51 |     |     )
  52 |     |         internal
  53 |     |         view
  54 |     |         override
  55 | *   |         returns (Execution[] memory executions)
  56 |     |     {
  57 | *   |         address yieldSource = data.extractYieldSource();
  58 | *   |         uint256 shares = _decodeAmount(data);
  59 | *   |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  60 |     | 
  61 | *   |         if (usePrevHookAmount) {
  62 | *   |             shares = ISuperHookResult(prevHook).getOutAmount(account);
  63 |     |         }
  64 |     | 
  65 |     |         if (shares == 0) revert AMOUNT_NOT_VALID();
  66 |     |         if (yieldSource == address(0) || account == address(0)) revert ADDRESS_NOT_VALID();
  67 |     | 
  68 |     |         executions = new Execution[](1);
  69 |     |         executions[0] = Execution({
  70 |     |             target: yieldSource,
  71 |     |             value: 0,
  72 |     |             callData: abi.encodeCall(IERC7540.requestRedeem, (shares, account, account))
  73 |     |         });
  74 |     |     }
  75 |     | 
  76 |     |     /// @inheritdoc ISuperHookAsyncCancelations
  77 |     |     function isAsyncCancelHook() external pure returns (CancelationType) {
  78 |     |         return CancelationType.NONE;
  79 |     |     }
  80 |     | 
  81 |     |     /*//////////////////////////////////////////////////////////////
  82 |     |                                  EXTERNAL METHODS
  83 |     |     //////////////////////////////////////////////////////////////*/
  84 |     | 
  85 |     |     /// @inheritdoc ISuperHookInflowOutflow
  86 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  87 |     |         return _decodeAmount(data);
  88 |     |     }
  89 |     | 
  90 |     |     /// @inheritdoc ISuperHookContextAware
  91 | *   |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  92 | *   |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  93 |     |     }
  94 |     | 
  95 |     |     /// @inheritdoc ISuperHookInspector
  96 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  97 | *   |         return abi.encodePacked(data.extractYieldSource());
  98 |     |     }
  99 |     | 
 100 |     |     /*//////////////////////////////////////////////////////////////
 101 |     |                                  INTERNAL METHODS
 102 |     |     //////////////////////////////////////////////////////////////*/
 103 |     | 
 104 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
 105 |     |         _setOutAmount(_getBalance(account, data), account);
 106 |     |     }
 107 |     | 
 108 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 109 |     |         _setOutAmount(getOutAmount(account) - _getBalance(account, data), account);
 110 |     |     }
 111 |     | 
 112 |     |     /*//////////////////////////////////////////////////////////////
 113 |     |                                  PRIVATE METHODS
 114 |     |     //////////////////////////////////////////////////////////////*/
 115 |     | 
 116 | *   |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 117 | *   |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 118 |     |     }
 119 |     | 
 120 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 121 | *   |         return IERC20(IERC7540(data.extractYieldSource()).share()).balanceOf(account);
 122 |     |     }
 123 |     | }
 124 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/7540/Withdraw7540VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
   8 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import {
  13 |     |     ISuperHookResultOutflow,
  14 |     |     ISuperHookInflowOutflow,
  15 |     |     ISuperHookOutflow,
  16 |     |     ISuperHookContextAware,
  17 |     |     ISuperHookInspector
  18 |     | } from "../../../interfaces/ISuperHook.sol";
  19 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  20 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  21 |     | 
  22 |     | /// @title Withdraw7540VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @notice Compatible only with ERC-7540 vaults where `requestId` is non-fungible
  25 |     | /// @dev data has the following structure
  26 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  27 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  28 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 52);
  29 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 84);
  30 | *   | contract Withdraw7540VaultHook is BaseHook, ISuperHookInflowOutflow, ISuperHookOutflow, ISuperHookContextAware {
  31 |     |     using HookDataDecoder for bytes;
  32 |     | 
  33 |     |     uint256 private constant AMOUNT_POSITION = 52;
  34 |     |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 84;
  35 |     | 
  36 | *   |     constructor() BaseHook(HookType.OUTFLOW, HookSubTypes.ERC7540) { }
  37 |     | 
  38 |     |     /*//////////////////////////////////////////////////////////////
  39 |     |                                  VIEW METHODS
  40 |     |     //////////////////////////////////////////////////////////////*/
  41 |     |     /// @inheritdoc BaseHook
  42 |     |     function _buildHookExecutions(
  43 |     |         address prevHook,
  44 |     |         address account,
  45 |     |         bytes calldata data
  46 |     |     )
  47 |     |         internal
  48 |     |         view
  49 |     |         override
  50 |     |         returns (Execution[] memory executions)
  51 |     |     {
  52 |     |         address yieldSource = data.extractYieldSource();
  53 |     |         uint256 amount = _decodeAmount(data);
  54 |     |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  55 |     | 
  56 |     |         if (usePrevHookAmount) {
  57 |     |             amount = ISuperHookResultOutflow(prevHook).getOutAmount(account);
  58 |     |         }
  59 |     | 
  60 |     |         if (amount == 0) revert AMOUNT_NOT_VALID();
  61 |     |         if (yieldSource == address(0) || account == address(0)) revert ADDRESS_NOT_VALID();
  62 |     | 
  63 |     |         executions = new Execution[](1);
  64 |     |         executions[0] = Execution({
  65 |     |             target: yieldSource,
  66 |     |             value: 0,
  67 |     |             callData: abi.encodeCall(IERC7540.withdraw, (amount, account, account))
  68 |     |         });
  69 |     |     }
  70 |     | 
  71 |     |     /*//////////////////////////////////////////////////////////////
  72 |     |                                  EXTERNAL METHODS
  73 |     |     //////////////////////////////////////////////////////////////*/
  74 |     | 
  75 |     |     /// @inheritdoc ISuperHookInflowOutflow
  76 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  77 |     |         return _decodeAmount(data);
  78 |     |     }
  79 |     | 
  80 |     |     /// @inheritdoc ISuperHookContextAware
  81 |     |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  82 |     |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  83 |     |     }
  84 |     | 
  85 |     |     /// @inheritdoc ISuperHookOutflow
  86 |     |     function replaceCalldataAmount(bytes memory data, uint256 amount) external pure returns (bytes memory) {
  87 |     |         return _replaceCalldataAmount(data, amount, AMOUNT_POSITION);
  88 |     |     }
  89 |     | 
  90 |     |     /// @inheritdoc ISuperHookInspector
  91 |     |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  92 |     |         return abi.encodePacked(data.extractYieldSource());
  93 |     |     }
  94 |     | 
  95 |     |     /*//////////////////////////////////////////////////////////////
  96 |     |                                  INTERNAL METHODS
  97 |     |     //////////////////////////////////////////////////////////////*/
  98 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
  99 |     |         address yieldSource = data.extractYieldSource();
 100 |     |         asset = IERC7540(yieldSource).asset();
 101 |     |         _setOutAmount(_getBalance(account, data), account);
 102 |     |         usedShares = _getSharesBalance(account, data);
 103 |     |         spToken = IERC7540(yieldSource).share();
 104 |     |     }
 105 |     | 
 106 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 107 |     |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 108 |     |         usedShares = usedShares - _getSharesBalance(account, data);
 109 |     |     }
 110 |     | 
 111 |     |     /*//////////////////////////////////////////////////////////////
 112 |     |                                  PRIVATE METHODS
 113 |     |     //////////////////////////////////////////////////////////////*/
 114 |     |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 115 |     |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 116 |     |     }
 117 |     | 
 118 |     |     function _getBalance(address account, bytes memory) private view returns (uint256) {
 119 |     |         return IERC20(asset).balanceOf(account);
 120 |     |     }
 121 |     | 
 122 |     |     function _getSharesBalance(address account, bytes memory data) private view returns (uint256) {
 123 |     |         address yieldSource = data.extractYieldSource();
 124 |     |         return IERC7540(yieldSource).claimableRedeemRequest(0, account);
 125 |     |     }
 126 |     | }
 127 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/super-vault/CancelRedeemHook.sol
  1 |     | // SPDX-License-Identifier: Apache-2.0
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | // external
  5 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
  6 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
  7 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
  8 |     | 
  9 |     | // Superform
 10 |     | import { BaseHook } from "../../BaseHook.sol";
 11 |     | import { VaultBankLockableHook } from "../../VaultBankLockableHook.sol";
 12 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
 13 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
 14 |     | import { ISuperVault } from "../../../vendor/superform/ISuperVault.sol";
 15 |     | import { ISuperHookAsyncCancelations, ISuperHookInspector } from "../../../interfaces/ISuperHook.sol";
 16 |     | 
 17 |     | /// @title CancelRedeemHook
 18 |     | /// @author Superform Labs
 19 |     | /// @dev data has the following structure
 20 |     | /// @notice         bytes32 placeholder = bytes32(BytesLib.slice(data, 0, 32), 0);
 21 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
 22 | *   | contract CancelRedeemHook is BaseHook, VaultBankLockableHook, ISuperHookAsyncCancelations {
 23 |     |     using HookDataDecoder for bytes;
 24 |     | 
 25 | *   |     constructor() BaseHook(HookType.NONACCOUNTING, HookSubTypes.CANCEL_REDEEM) { }
 26 |     | 
 27 |     |     /*//////////////////////////////////////////////////////////////
 28 |     |                                  VIEW METHODS
 29 |     |     //////////////////////////////////////////////////////////////*/
 30 | *   |     function _buildHookExecutions(
 31 |     |         address,
 32 |     |         address account,
 33 |     |         bytes calldata data
 34 |     |     )
 35 |     |         internal
 36 |     |         pure
 37 |     |         override
 38 | *   |         returns (Execution[] memory executions)
 39 |     |     {
 40 | *   |         address yieldSource = data.extractYieldSource();
 41 |     | 
 42 | *   |         if (yieldSource == address(0) || account == address(0)) revert ADDRESS_NOT_VALID();
 43 |     | 
 44 | *   |         executions = new Execution[](1);
 45 | *   |         executions[0] =
 46 | *   |             Execution({ target: yieldSource, value: 0, callData: abi.encodeCall(ISuperVault.cancelRedeem, (account)) });
 47 |     |     }
 48 |     | 
 49 |     |     /*//////////////////////////////////////////////////////////////
 50 |     |                                  EX`TERNAL METHODS
 51 |     |     //////////////////////////////////////////////////////////////*/
 52 |     | 
 53 |     |     /// @inheritdoc ISuperHookAsyncCancelations
 54 |     |     function isAsyncCancelHook() external pure returns (CancelationType) {
 55 |     |         return CancelationType.OUTFLOW;
 56 |     |     }
 57 |     | 
 58 |     |     /// @inheritdoc ISuperHookInspector
 59 | *   |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
 60 | *   |         return abi.encodePacked(data.extractYieldSource());
 61 |     |     }
 62 |     | 
 63 |     |     /*//////////////////////////////////////////////////////////////
 64 |     |                                  INTERNAL METHODS
 65 |     |     //////////////////////////////////////////////////////////////*/
 66 | *   |     function _preExecute(address, address account, bytes calldata data) internal override {
 67 | *   |         _setOutAmount(_getBalance(account, data), account);
 68 | *   |         spToken = data.extractYieldSource();
 69 |     |     }
 70 |     | 
 71 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 72 | *   |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 73 |     |     }
 74 |     |     /*//////////////////////////////////////////////////////////////
 75 |     |                                  PRIVATE METHODS
 76 |     |     //////////////////////////////////////////////////////////////*/
 77 |     | 
 78 | *   |     function _getBalance(address account, bytes memory data) private view returns (uint256) {
 79 | *   |         return IERC20(IERC7540(data.extractYieldSource()).share()).balanceOf(account);
 80 |     |     }
 81 |     | }
 82 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/hooks/vaults/super-vault/Withdraw7540VaultHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { BytesLib } from "../../../vendor/BytesLib.sol";
   6 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   7 |     | import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
   8 |     | import { IERC7540 } from "../../../vendor/vaults/7540/IERC7540.sol";
   9 |     | 
  10 |     | // Superform
  11 |     | import { BaseHook } from "../../BaseHook.sol";
  12 |     | import {
  13 |     |     ISuperHookResultOutflow,
  14 |     |     ISuperHookInflowOutflow,
  15 |     |     ISuperHookOutflow,
  16 |     |     ISuperHookContextAware,
  17 |     |     ISuperHookInspector
  18 |     | } from "../../../interfaces/ISuperHook.sol";
  19 |     | import { HookSubTypes } from "../../../libraries/HookSubTypes.sol";
  20 |     | import { HookDataDecoder } from "../../../libraries/HookDataDecoder.sol";
  21 |     | 
  22 |     | /// @title Withdraw7540VaultHook
  23 |     | /// @author Superform Labs
  24 |     | /// @notice Compatible only with ERC-7540 vaults where `requestId` is non-fungible
  25 |     | /// @dev data has the following structure
  26 |     | /// @notice         bytes32 yieldSourceOracleId = bytes32(BytesLib.slice(data, 0, 32), 0);
  27 |     | /// @notice         address yieldSource = BytesLib.toAddress(data, 32);
  28 |     | /// @notice         uint256 amount = BytesLib.toUint256(data, 52);
  29 |     | /// @notice         bool usePrevHookAmount = _decodeBool(data, 84);
  30 | *   | contract Withdraw7540VaultHook is BaseHook, ISuperHookInflowOutflow, ISuperHookOutflow, ISuperHookContextAware {
  31 |     |     using HookDataDecoder for bytes;
  32 |     | 
  33 |     |     uint256 private constant AMOUNT_POSITION = 52;
  34 |     |     uint256 private constant USE_PREV_HOOK_AMOUNT_POSITION = 84;
  35 |     | 
  36 | *   |     constructor() BaseHook(HookType.OUTFLOW, HookSubTypes.ERC7540) { }
  37 |     | 
  38 |     |     /*//////////////////////////////////////////////////////////////
  39 |     |                                  VIEW METHODS
  40 |     |     //////////////////////////////////////////////////////////////*/
  41 |     |     /// @inheritdoc BaseHook
  42 |     |     function _buildHookExecutions(
  43 |     |         address prevHook,
  44 |     |         address account,
  45 |     |         bytes calldata data
  46 |     |     )
  47 |     |         internal
  48 |     |         view
  49 |     |         override
  50 |     |         returns (Execution[] memory executions)
  51 |     |     {
  52 |     |         address yieldSource = data.extractYieldSource();
  53 |     |         uint256 amount = _decodeAmount(data);
  54 |     |         bool usePrevHookAmount = _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  55 |     | 
  56 |     |         if (usePrevHookAmount) {
  57 |     |             amount = ISuperHookResultOutflow(prevHook).getOutAmount(account);
  58 |     |         }
  59 |     | 
  60 |     |         if (amount == 0) revert AMOUNT_NOT_VALID();
  61 |     |         if (yieldSource == address(0) || account == address(0)) revert ADDRESS_NOT_VALID();
  62 |     | 
  63 |     |         executions = new Execution[](1);
  64 |     |         executions[0] = Execution({
  65 |     |             target: yieldSource,
  66 |     |             value: 0,
  67 |     |             callData: abi.encodeCall(IERC7540.withdraw, (amount, account, account))
  68 |     |         });
  69 |     |     }
  70 |     | 
  71 |     |     /*//////////////////////////////////////////////////////////////
  72 |     |                                  EXTERNAL METHODS
  73 |     |     //////////////////////////////////////////////////////////////*/
  74 |     | 
  75 |     |     /// @inheritdoc ISuperHookInflowOutflow
  76 |     |     function decodeAmount(bytes memory data) external pure returns (uint256) {
  77 |     |         return _decodeAmount(data);
  78 |     |     }
  79 |     | 
  80 |     |     /// @inheritdoc ISuperHookContextAware
  81 |     |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool) {
  82 |     |         return _decodeBool(data, USE_PREV_HOOK_AMOUNT_POSITION);
  83 |     |     }
  84 |     | 
  85 |     |     /// @inheritdoc ISuperHookOutflow
  86 |     |     function replaceCalldataAmount(bytes memory data, uint256 amount) external pure returns (bytes memory) {
  87 |     |         return _replaceCalldataAmount(data, amount, AMOUNT_POSITION);
  88 |     |     }
  89 |     | 
  90 |     |     /// @inheritdoc ISuperHookInspector
  91 |     |     function inspect(bytes calldata data) external pure override returns (bytes memory) {
  92 |     |         return abi.encodePacked(data.extractYieldSource());
  93 |     |     }
  94 |     | 
  95 |     |     /*//////////////////////////////////////////////////////////////
  96 |     |                                  INTERNAL METHODS
  97 |     |     //////////////////////////////////////////////////////////////*/
  98 |     |     function _preExecute(address, address account, bytes calldata data) internal override {
  99 |     |         address yieldSource = data.extractYieldSource();
 100 |     |         asset = IERC7540(yieldSource).asset();
 101 |     |         _setOutAmount(_getBalance(account, data), account);
 102 |     |         usedShares = _getSharesBalance(account, data);
 103 |     |         spToken = IERC7540(yieldSource).share();
 104 |     |     }
 105 |     | 
 106 |     |     function _postExecute(address, address account, bytes calldata data) internal override {
 107 |     |         _setOutAmount(_getBalance(account, data) - getOutAmount(account), account);
 108 |     |         usedShares = usedShares - _getSharesBalance(account, data);
 109 |     |     }
 110 |     | 
 111 |     |     /*//////////////////////////////////////////////////////////////
 112 |     |                                  PRIVATE METHODS
 113 |     |     //////////////////////////////////////////////////////////////*/
 114 |     |     function _decodeAmount(bytes memory data) private pure returns (uint256) {
 115 |     |         return BytesLib.toUint256(data, AMOUNT_POSITION);
 116 |     |     }
 117 |     | 
 118 |     |     function _getBalance(address account, bytes memory) private view returns (uint256) {
 119 |     |         return IERC20(asset).balanceOf(account);
 120 |     |     }
 121 |     | 
 122 |     |     function _getSharesBalance(address account, bytes memory data) private view returns (uint256) {
 123 |     |         address yieldSource = data.extractYieldSource();
 124 |     |         return IERC7540(yieldSource).claimableRedeemRequest(0, account);
 125 |     |     }
 126 |     | }
 127 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/interfaces/ISuperHook.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // external
   5 |     | import { Execution } from "modulekit/accounts/erc7579/lib/ExecutionLib.sol";
   6 |     | 
   7 |     | /**
   8 |     |  * @title SuperHook System
   9 |     |  * @author Superform Labs
  10 |     |  * @notice The hook system provides a modular and composable way to execute operations on assets
  11 |     |  * @dev The hook system architecture consists of several interfaces that work together:
  12 |     |  *      - ISuperHook: The base interface all hooks implement, with lifecycle methods
  13 |     |  *      - ISuperHookResult: Provides execution results and output information
  14 |     |  *      - Specialized interfaces (ISuperHookOutflow, ISuperHookLoans, etc.) for specific behaviors
  15 |     |  *
  16 |     |  * Hooks are executed in sequence, where each hook can access the results from previous hooks.
  17 |     |  * The three main types of hooks are:
  18 |     |  *      - NONACCOUNTING: Utility hooks that don't update the accounting system
  19 |     |  *      - INFLOW: Hooks that process deposits or additions to positions
  20 |     |  *      - OUTFLOW: Hooks that process withdrawals or reductions to positions
  21 |     |  */
  22 |     | interface ISuperLockableHook {
  23 |     |     /// @notice The vault bank address used to lock SuperPositions
  24 |     |     /// @dev Only relevant for cross-chain operations where positions are locked
  25 |     |     /// @return The vault bank address, or address(0) if not applicable
  26 |     |     function vaultBank() external view returns (address);
  27 |     | 
  28 |     |     /// @notice The destination chain ID for cross-chain operations
  29 |     |     /// @dev Used to identify the target chain for cross-chain position transfers
  30 |     |     /// @return The destination chain ID, or 0 if not a cross-chain operation
  31 |     |     function dstChainId() external view returns (uint256);
  32 |     | }
  33 |     | 
  34 |     | interface ISuperHookSetter {
  35 |     |     /// @notice Sets the output amount for the hook
  36 |     |     /// @dev Used for updating `outAmount` when fees were deducted
  37 |     |     /// @param outAmount The amount of tokens processed by the hook
  38 |     |     /// @param caller The caller address for context identification
  39 |     |     function setOutAmount(uint256 outAmount, address caller) external;
  40 |     | }
  41 |     | /// @title ISuperHookInspector
  42 |     | /// @author Superform Labs
  43 |     | /// @notice Interface for the SuperHookInspector contract that manages hook inspection
  44 |     | 
  45 |     | interface ISuperHookInspector {
  46 |     |     /// @notice Inspect the hook
  47 |     |     /// @param data The hook data to inspect
  48 |     |     /// @return argsEncoded The arguments of the hook encoded
  49 |     |     function inspect(bytes calldata data) external view returns (bytes memory argsEncoded);
  50 |     | }
  51 |     | 
  52 |     | /// @title ISuperHookResult
  53 |     | /// @author Superform Labs
  54 |     | /// @notice Interface that exposes the result of a hook execution
  55 |     | /// @dev All hooks must implement this interface to provide standardized access to execution results.
  56 |     | ///      These results are used by subsequent hooks in the execution chain and by the executor.
  57 |     | interface ISuperHookResult {
  58 |     |     /*//////////////////////////////////////////////////////////////
  59 |     |                                  VIEW METHODS
  60 |     |     //////////////////////////////////////////////////////////////*/
  61 |     | 
  62 |     |     /// @notice The type of hook
  63 |     |     /// @dev Used to determine how accounting should process this hook's results
  64 |     |     /// @return The hook type (NONACCOUNTING, INFLOW, or OUTFLOW)
  65 |     |     function hookType() external view returns (ISuperHook.HookType);
  66 |     | 
  67 |     |     /// @notice The SuperPosition (SP) token associated with this hook
  68 |     |     /// @dev For vault hooks, this would be the tokenized position representing shares
  69 |     |     /// @return The address of the SP token, or address(0) if not applicable
  70 |     |     function spToken() external view returns (address);
  71 |     | 
  72 |     |     /// @notice The underlying asset token being processed
  73 |     |     /// @dev For most hooks, this is the actual token being deposited or withdrawn
  74 |     |     /// @return The address of the asset token, or address(0) for native assets
  75 |     |     function asset() external view returns (address);
  76 |     | 
  77 |     |     /// @notice The amount of tokens processed by the hook in a given caller context, subject to fees after update
  78 |     |     /// @dev This is the primary output value used by subsequent hooks
  79 |     |     /// @param caller The caller address for context identification
  80 |     |     /// @return The amount of tokens (assets or shares) processed
  81 |     |     function getOutAmount(address caller) external view returns (uint256);
  82 |     | }
  83 |     | 
  84 |     | /// @title ISuperHookContextAware
  85 |     | /// @author Superform Labs
  86 |     | /// @notice Interface for hooks that can use previous hook results in their execution
  87 |     | /// @dev Enables contextual awareness and data flow between hooks in a chain
  88 |     | interface ISuperHookContextAware {
  89 |     |     /// @notice Determines if this hook should use the amount from the previous hook
  90 |     |     /// @dev Used to create hook chains where output from one hook becomes input to the next
  91 |     |     /// @param data The hook-specific data containing configuration
  92 |     |     /// @return True if the hook should use the previous hook's output amount
  93 |     |     function decodeUsePrevHookAmount(bytes memory data) external pure returns (bool);
  94 |     | }
  95 |     | 
  96 |     | /// @title ISuperHookInflowOutflow
  97 |     | /// @author Superform Labs
  98 |     | /// @notice Interface for hooks that handle both inflows and outflows
  99 |     | /// @dev Provides standardized amount extraction for both deposit and withdrawal operations
 100 |     | interface ISuperHookInflowOutflow {
 101 |     |     /// @notice Extracts the amount from the hook's calldata
 102 |     |     /// @dev Used to determine the quantity of assets or shares being processed
 103 |     |     /// @param data The hook-specific calldata containing the amount
 104 |     |     /// @return The amount of tokens to process
 105 |     |     function decodeAmount(bytes memory data) external pure returns (uint256);
 106 |     | }
 107 |     | 
 108 |     | /// @title ISuperHookOutflow
 109 |     | /// @author Superform Labs
 110 |     | /// @notice Interface for hooks that specifically handle outflows (withdrawals)
 111 |     | /// @dev Provides additional functionality needed only for outflow operations
 112 |     | interface ISuperHookOutflow {
 113 |     |     /// @notice Replace the amount in the calldata
 114 |     |     /// @param data The data to replace the amount in
 115 |     |     /// @param amount The amount to replace
 116 |     |     /// @return data The data with the replaced amount
 117 |     |     function replaceCalldataAmount(bytes memory data, uint256 amount) external pure returns (bytes memory);
 118 |     | }
 119 |     | 
 120 |     | /// @title ISuperHookResultOutflow
 121 |     | /// @author Superform Labs
 122 |     | /// @notice Extended result interface for outflow hook operations
 123 |     | /// @dev Extends the base result interface with outflow-specific information
 124 |     | interface ISuperHookResultOutflow is ISuperHookResult {
 125 |     |     /// @notice The amount of shares consumed during outflow processing
 126 |     |     /// @dev Used for cost basis calculation in the accounting system
 127 |     |     /// @return The amount of shares consumed from the user's position
 128 |     |     function usedShares() external view returns (uint256);
 129 |     | }
 130 |     | 
 131 |     | /// @title ISuperHookLoans
 132 |     | /// @author Superform Labs
 133 |     | /// @notice Interface for hooks that interact with lending protocols
 134 |     | /// @dev Extends context awareness to enable loan operations within hook chains
 135 |     | interface ISuperHookLoans is ISuperHookContextAware {
 136 |     |     /// @notice Gets the address of the token being borrowed
 137 |     |     /// @dev Used to identify which asset is being borrowed from the lending protocol
 138 |     |     /// @param data The hook-specific data containing loan information
 139 |     |     /// @return The address of the borrowed token
 140 |     |     function getLoanTokenAddress(bytes memory data) external pure returns (address);
 141 |     | 
 142 |     |     /// @notice Gets the address of the token used as collateral
 143 |     |     /// @dev Used to identify which asset is being used to secure the loan
 144 |     |     /// @param data The hook-specific data containing collateral information
 145 |     |     /// @return The address of the collateral token
 146 |     |     function getCollateralTokenAddress(bytes memory data) external view returns (address);
 147 |     | 
 148 |     |     /// @notice Gets the current loan token balance for an account
 149 |     |     /// @dev Used to track outstanding loan amounts
 150 |     |     /// @param account The account to check the loan balance for
 151 |     |     /// @param data The hook-specific data containing loan parameters
 152 |     |     /// @return The amount of tokens currently borrowed
 153 |     |     function getLoanTokenBalance(address account, bytes memory data) external view returns (uint256);
 154 |     | 
 155 |     |     /// @notice Gets the current collateral token balance for an account
 156 |     |     /// @dev Used to track collateral positions
 157 |     |     /// @param account The account to check the collateral balance for
 158 |     |     /// @param data The hook-specific data containing collateral parameters
 159 |     |     /// @return The amount of tokens currently used as collateral
 160 |     |     function getCollateralTokenBalance(address account, bytes memory data) external view returns (uint256);
 161 |     | }
 162 |     | 
 163 |     | /// @title ISuperHookAsyncCancelations
 164 |     | /// @author Superform Labs
 165 |     | /// @notice Interface for hooks that can cancel asynchronous operations
 166 |     | /// @dev Used to handle cancellation of pending operations that haven't completed
 167 |     | interface ISuperHookAsyncCancelations {
 168 |     |     /// @notice Types of cancellations that can be performed
 169 |     |     /// @dev Distinguishes between different operation types that can be canceled
 170 |     |     enum CancelationType {
 171 |     |         NONE, // Not a cancelation hook
 172 |     |         INFLOW, // Cancels a pending deposit operation
 173 |     |         OUTFLOW // Cancels a pending withdrawal operation
 174 |     | 
 175 |     |     }
 176 |     | 
 177 |     |     /// @notice Identifies the type of async operation this hook can cancel
 178 |     |     /// @dev Used to verify the hook is appropriate for the operation being canceled
 179 |     |     /// @return asyncType The type of cancellation this hook performs
 180 |     |     function isAsyncCancelHook() external pure returns (CancelationType asyncType);
 181 |     | }
 182 |     | 
 183 |     | /// @title ISuperHook
 184 |     | /// @author Superform Labs
 185 |     | /// @notice The core hook interface that all hooks must implement
 186 |     | /// @dev Defines the lifecycle methods and execution flow for the hook system
 187 |     | ///      Hooks are executed in sequence with results passed between them
 188 |     | interface ISuperHook {
 189 |     |     /*//////////////////////////////////////////////////////////////
 190 |     | 
 191 |     |                                  ENUMS
 192 |     |     //////////////////////////////////////////////////////////////*/
 193 |     |     /// @notice Defines the possible types of hooks in the system
 194 |     |     /// @dev Used to determine how the hook affects accounting and what operations it performs
 195 |     |     enum HookType {
 196 |     |         NONACCOUNTING, // Hook doesn't affect accounting (e.g., a swap or bridge)
 197 |     |         INFLOW, // Hook processes deposits or positions being added
 198 |     |         OUTFLOW // Hook processes withdrawals or positions being removed
 199 |     | 
 200 |     |     }
 201 |     | 
 202 |     |     /*//////////////////////////////////////////////////////////////
 203 |     |                                  VIEW METHODS
 204 |     |     //////////////////////////////////////////////////////////////*/
 205 |     |     /// @notice Builds the execution array for the hook operation
 206 |     |     /// @dev This is the core method where hooks define their on-chain interactions
 207 |     |     ///      The returned executions are a sequence of contract calls to perform
 208 |     |     ///      No state changes should occur in this method
 209 |     |     /// @param prevHook The address of the previous hook in the chain, or address(0) if first
 210 |     |     /// @param account The account to perform executions for (usually an ERC7579 account)
 211 |     |     /// @param data The hook-specific parameters and configuration data
 212 |     |     /// @return executions Array of Execution structs defining calls to make
 213 |     |     function build(
 214 |     |         address prevHook,
 215 |     |         address account,
 216 |     |         bytes calldata data
 217 |     |     )
 218 |     |         external
 219 |     |         view
 220 |     |         returns (Execution[] memory executions);
 221 |     | 
 222 |     |     /*//////////////////////////////////////////////////////////////
 223 |     |                                  PUBLIC METHODS
 224 |     |     //////////////////////////////////////////////////////////////*/
 225 |     |     /// @notice Prepares the hook for execution
 226 |     |     /// @dev Called before the main execution, used to validate inputs and set execution context
 227 |     |     ///      This method may perform state changes to set up the hook's execution state
 228 |     |     /// @param prevHook The address of the previous hook in the chain, or address(0) if first
 229 |     |     /// @param account The account to perform operations for
 230 |     |     /// @param data The hook-specific parameters and configuration data
 231 |     |     function preExecute(address prevHook, address account, bytes memory data) external;
 232 |     | 
 233 |     |     /// @notice Finalizes the hook after execution
 234 |     |     /// @dev Called after the main execution, used to update hook state and calculate results
 235 |     |     ///      Sets output values (outAmount, usedShares, etc.) for subsequent hooks
 236 |     |     /// @param prevHook The address of the previous hook in the chain, or address(0) if first
 237 |     |     /// @param account The account operations were performed for
 238 |     |     /// @param data The hook-specific parameters and configuration data
 239 |     |     function postExecute(address prevHook, address account, bytes memory data) external;
 240 |     | 
 241 |     |     /// @notice Returns the specific subtype identification for this hook
 242 |     |     /// @dev Used to categorize hooks beyond the basic HookType
 243 |     |     ///      For example, a hook might be of type INFLOW but subtype VAULT_DEPOSIT
 244 |     |     /// @return A bytes32 identifier for the specific hook functionality
 245 |     |     function subtype() external view returns (bytes32);
 246 |     | 
 247 |     |     /// @notice Resets hook mutexes
 248 |     |     /// @param caller The caller address for context identification
 249 |     |     function resetExecutionState(address caller) external;
 250 |     | 
 251 |     |     /// @notice Sets the caller address that initiated the execution
 252 |     |     /// @dev Used for security validation between preExecute and postExecute calls
 253 |     |     /// @param caller The caller address for context identification
 254 |     |     function setExecutionContext(address caller) external;
 255 |     | 
 256 |     |     /// @notice Returns the execution nonce for the current execution context
 257 |     |     /// @dev Used to ensure unique execution contexts and prevent replay attacks
 258 |     |     /// @return The execution nonce
 259 |     |     function executionNonce() external view returns (uint256);
 260 |     | 
 261 |     |     /// @notice Returns the last caller registered by `setExecutionContext`
 262 |     |     /// @return The last caller address
 263 |     |     function lastCaller() external view returns (address);
 264 |     | }
 265 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/interfaces/accounting/IYieldSourceOracle.sol
   1 |     | // SPDX-License-Identifier: Apache-2.0
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // Superform
   5 |     | import { IOracle } from "../../vendor/awesome-oracles/IOracle.sol";
   6 |     | 
   7 |     | /// @title IYieldSourceOracle
   8 |     | /// @author Superform Labs
   9 |     | /// @notice Interface for oracles that provide price and TVL data for yield-bearing assets
  10 |     | interface IYieldSourceOracle {
  11 |     |     /*//////////////////////////////////////////////////////////////
  12 |     |                                 ERRORS
  13 |     |     //////////////////////////////////////////////////////////////*/
  14 |     | 
  15 |     |     /// @notice Error when array lengths do not match in batch operations
  16 |     |     /// @dev Thrown when the lengths of input arrays in multi-asset operations don't match
  17 |     |     error ARRAY_LENGTH_MISMATCH();
  18 |     | 
  19 |     |     /// @notice Error when base asset is not valid for the yield source
  20 |     |     /// @dev Thrown when attempting to use an asset that isn't supported by the yield source
  21 |     |     error INVALID_BASE_ASSET();
  22 |     | 
  23 |     |     /*//////////////////////////////////////////////////////////////
  24 |     |                                 STRUCTS
  25 |     |     //////////////////////////////////////////////////////////////*/
  26 |     | 
  27 |     |     /// @notice Struct to hold local variables for getTVLMultipleUSD
  28 |     |     /// @dev Used to manage complex computation state without stack-too-deep errors
  29 |     |     ///      These variables support the calculation of USD-denominated TVL values
  30 |     |     ///      across multiple yield sources and owners
  31 |     |     struct TVLMultipleUSDVars {
  32 |     |         /// @notice Number of yield sources being processed
  33 |     |         uint256 length;
  34 |     |         /// @notice Number of share owners being processed
  35 |     |         uint256 ownersLength;
  36 |     |         /// @notice Base amount in the underlying asset's native units
  37 |     |         uint256 baseAmount;
  38 |     |         /// @notice Accumulated TVL in USD for a specific user
  39 |     |         uint256 userTvlUSD;
  40 |     |         /// @notice Accumulated total TVL in USD across all sources
  41 |     |         uint256 totalTvlUSD;
  42 |     |         /// @notice Current yield source being processed
  43 |     |         address yieldSource;
  44 |     |         /// @notice Array of addresses that own shares in the yield source
  45 |     |         address[] owners;
  46 |     |         /// @notice Oracle registry used for price conversions
  47 |     |         IOracle registry;
  48 |     |     }
  49 |     | 
  50 |     |     /*//////////////////////////////////////////////////////////////
  51 |     |                             VIEW METHODS
  52 |     |     //////////////////////////////////////////////////////////////*/
  53 |     | 
  54 |     |     /// @notice Returns the number of decimals of the yield source shares
  55 |     |     /// @dev Critical for accurately interpreting share amounts and calculating prices
  56 |     |     ///      Different yield sources may have different decimal precision
  57 |     |     /// @param yieldSourceAddress The address of the yield-bearing token contract
  58 |     |     /// @return decimals The number of decimals used by the yield source's share token
  59 |     |     function decimals(address yieldSourceAddress) external view returns (uint8);
  60 |     | 
  61 |     |     /// @notice Calculates the number of shares that would be received for a given amount of assets
  62 |     |     /// @dev Used for deposit simulations and to calculate current exchange rates
  63 |     |     /// @param yieldSourceAddress The yield-bearing token address (e.g., aUSDC, cDAI)
  64 |     |     /// @param assetIn The underlying asset being deposited (e.g., USDC, DAI)
  65 |     |     /// @param assetsIn The amount of underlying assets to deposit, in the asset's native units
  66 |     |     /// @return shares The number of yield-bearing shares that would be received
  67 |     |     function getShareOutput(
  68 |     |         address yieldSourceAddress,
  69 |     |         address assetIn,
  70 |     |         uint256 assetsIn
  71 |     |     )
  72 |     |         external
  73 |     |         view
  74 |     |         returns (uint256);
  75 |     | 
  76 |     |     /// @notice Calculates the number of underlying assets that would be received for a given amount of shares
  77 |     |     /// @dev Used for withdrawal simulations and to calculate current yield
  78 |     |     /// @param yieldSourceAddress The yield-bearing token address (e.g., aUSDC, cDAI)
  79 |     |     /// @param assetIn The underlying asset to receive (e.g., USDC, DAI)
  80 |     |     /// @param sharesIn The amount of yield-bearing shares to redeem
  81 |     |     /// @return assets The number of underlying assets that would be received
  82 |     |     function getAssetOutput(
  83 |     |         address yieldSourceAddress,
  84 |     |         address assetIn,
  85 |     |         uint256 sharesIn
  86 |     |     )
  87 |     |         external
  88 |     |         view
  89 |     |         returns (uint256);
  90 |     | 
  91 |     |     /// @notice Retrieves the current price per share in terms of the underlying asset
  92 |     |     /// @dev Core function for calculating yields and determining returns
  93 |     |     /// @param yieldSourceAddress The yield-bearing token address to get the price for
  94 |     |     /// @return pricePerShare The current price per share in underlying asset terms, scaled by decimals
  95 |     |     function getPricePerShare(address yieldSourceAddress) external view returns (uint256);
  96 |     | 
  97 |     |     /// @notice Calculates the total value locked in a yield source by a specific owner
  98 |     |     /// @dev Used to track individual position sizes within the system
  99 |     |     /// @param yieldSourceAddress The yield-bearing token address to check
 100 |     |     /// @param ownerOfShares The address owning the yield-bearing tokens
 101 |     |     /// @return tvl The total value locked by the owner, in underlying asset terms
 102 |     |     function getTVLByOwnerOfShares(address yieldSourceAddress, address ownerOfShares) external view returns (uint256);
 103 |     | 
 104 |     |     /// @notice Gets the share balance of a specific owner in a yield source
 105 |     |     /// @dev Returns raw share balance without converting to underlying assets
 106 |     |     ///      Used to track participation in the system and for accounting
 107 |     |     /// @param yieldSourceAddress The yield-bearing token address
 108 |     |     /// @param ownerOfShares The address to check the balance for
 109 |     |     /// @return balance The number of yield-bearing tokens owned by the address
 110 |     |     function getBalanceOfOwner(address yieldSourceAddress, address ownerOfShares) external view returns (uint256);
 111 |     | 
 112 |     |     /// @notice Calculates the total value locked across all users in a yield source
 113 |     |     /// @dev Critical for monitoring the size of each yield source in the system
 114 |     |     /// @param yieldSourceAddress The yield-bearing token address to check
 115 |     |     /// @return tvl The total value locked in the yield source, in underlying asset terms
 116 |     |     function getTVL(address yieldSourceAddress) external view returns (uint256);
 117 |     | 
 118 |     |     /// @notice Batch version of getPricePerShare for multiple yield sources
 119 |     |     /// @dev Efficiently retrieves current prices for multiple yield sources
 120 |     |     /// @param yieldSourceAddresses Array of yield-bearing token addresses
 121 |     |     /// @return pricesPerShare Array of current prices for each yield source
 122 |     |     function getPricePerShareMultiple(address[] memory yieldSourceAddresses)
 123 |     |         external
 124 |     |         view
 125 |     |         returns (uint256[] memory pricesPerShare);
 126 |     | 
 127 |     |     /// @notice Batch version of getTVLByOwnerOfShares for multiple yield sources and owners
 128 |     |     /// @dev Efficiently calculates TVL for multiple owners across multiple yield sources
 129 |     |     /// @param yieldSourceAddresses Array of yield-bearing token addresses
 130 |     |     /// @param ownersOfShares 2D array where each sub-array contains owner addresses for a yield source
 131 |     |     /// @return userTvls 2D array of TVL values for each owner in each yield source
 132 |     |     function getTVLByOwnerOfSharesMultiple(
 133 |     |         address[] memory yieldSourceAddresses,
 134 |     |         address[][] memory ownersOfShares
 135 |     |     )
 136 |     |         external
 137 |     |         view
 138 |     |         returns (uint256[][] memory userTvls);
 139 |     | 
 140 |     |     /// @notice Batch version of getTVL for multiple yield sources
 141 |     |     /// @dev Efficiently calculates total TVL across multiple yield sources
 142 |     |     /// @param yieldSourceAddresses Array of yield-bearing token addresses
 143 |     |     /// @return tvls Array containing the total TVL for each yield source
 144 |     |     function getTVLMultiple(address[] memory yieldSourceAddresses) external view returns (uint256[] memory tvls);
 145 |     | 
 146 |     |     /// @notice Calculates the asset output with fees added for an outflow operation
 147 |     |     /// @dev Gets the asset output from the oracle and adds any applicable fees
 148 |     |     ///      Uses try/catch to handle cases where oracle configuration doesn't exist
 149 |     |     /// @param yieldSourceOracleId Identifier for the yield source oracle configuration
 150 |     |     /// @param yieldSourceAddress Address of the yield-bearing asset
 151 |     |     /// @param assetOut Address of the output asset
 152 |     |     /// @param user Address of the user performing the outflow
 153 |     |     /// @param usedShares Amount of shares being withdrawn
 154 |     |     /// @return Total asset amount including fees
 155 |     |     function getAssetOutputWithFees(
 156 |     |         bytes32 yieldSourceOracleId,
 157 |     |         address yieldSourceAddress,
 158 |     |         address assetOut,
 159 |     |         address user,
 160 |     |         uint256 usedShares
 161 |     |     )
 162 |     |         external
 163 |     |         view
 164 |     |         returns (uint256);
 165 |     | }
 166 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/libraries/HookDataDecoder.sol
  1 |     | // SPDX-License-Identifier: Apache-2.0
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | import { BytesLib } from "../vendor/BytesLib.sol";
  5 |     | 
  6 |     | /// @title HookDataDecoder
  7 |     | /// @author Superform Labs
  8 |     | /// @notice Library for decoding hook data
  9 |     | library HookDataDecoder {
 10 |     |     function extractYieldSourceOracleId(bytes memory data) internal pure returns (bytes32) {
 11 |     |         return bytes32(BytesLib.slice(data, 0, 32));
 12 |     |     }
 13 |     | 
 14 | *   |     function extractYieldSource(bytes memory data) internal pure returns (address) {
 15 | *   |         return BytesLib.toAddress(data, 32);
 16 |     |     }
 17 |     | }
 18 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/libraries/HookSubTypes.sol
  1 |     | // SPDX-License-Identifier: Apache-2.0
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | /// @title HookSubTypes
  5 |     | /// @author Superform Labs
  6 |     | /// @notice Library for hook subtypes
  7 |     | library HookSubTypes {
  8 |     |     bytes32 public constant BRIDGE = keccak256(bytes("Bridge"));
  9 |     |     bytes32 public constant CANCEL_DEPOSIT = keccak256(bytes("CancelDeposit"));
 10 | *   |     bytes32 public constant CANCEL_DEPOSIT_REQUEST = keccak256(bytes("CancelDepositRequest"));
 11 | *   |     bytes32 public constant CANCEL_REDEEM = keccak256(bytes("CancelRedeem"));
 12 | *   |     bytes32 public constant CANCEL_REDEEM_REQUEST = keccak256(bytes("CancelRedeemRequest"));
 13 |     |     bytes32 public constant CLAIM = keccak256(bytes("Claim"));
 14 | *   |     bytes32 public constant CLAIM_CANCEL_DEPOSIT_REQUEST = keccak256(bytes("ClaimCancelDepositRequest"));
 15 | *   |     bytes32 public constant CLAIM_CANCEL_REDEEM_REQUEST = keccak256(bytes("ClaimCancelRedeemRequest"));
 16 |     |     bytes32 public constant COOLDOWN = keccak256(bytes("Cooldown"));
 17 |     |     bytes32 public constant ETHENA = keccak256(bytes("Ethena"));
 18 | *   |     bytes32 public constant ERC4626 = keccak256(bytes("ERC4626"));
 19 | *   |     bytes32 public constant ERC5115 = keccak256(bytes("ERC5115"));
 20 | *   |     bytes32 public constant ERC7540 = keccak256(bytes("ERC7540"));
 21 |     |     bytes32 public constant LOAN = keccak256(bytes("Loan"));
 22 |     |     bytes32 public constant LOAN_REPAY = keccak256(bytes("LoanRepay"));
 23 |     |     bytes32 public constant MISC = keccak256(bytes("Misc"));
 24 |     |     bytes32 public constant STAKE = keccak256(bytes("Stake"));
 25 |     |     bytes32 public constant SWAP = keccak256(bytes("Swap"));
 26 |     |     bytes32 public constant TOKEN = keccak256(bytes("Token"));
 27 |     |     bytes32 public constant UNSTAKE = keccak256(bytes("Unstake"));
 28 |     |     bytes32 public constant PTYT = keccak256(bytes("PTYT"));
 29 |     |     bytes32 public constant VAULT_BANK = keccak256(bytes("VaultBank"));
 30 |     | 
 31 |     |     function getHookSubType(string memory hookSubtype) internal pure returns (bytes32) {
 32 |     |         return keccak256(bytes(hookSubtype));
 33 |     |     }
 34 |     | }
 35 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/vendor/BytesLib.sol
   1 |     | // SPDX-License-Identifier: Unlicense
   2 |     | /*
   3 |     |  * @title Solidity Bytes Arrays Utils
   4 |     |  * @author Gonçalo Sá <goncalo.sa@consensys.net>
   5 |     |  *
   6 |     |  * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
   7 |     |  *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
   8 |     |  */
   9 |     | pragma solidity 0.8.30;
  10 |     | 
  11 |     | library BytesLib {
  12 |     |     function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {
  13 |     |         bytes memory tempBytes;
  14 |     | 
  15 |     |         assembly {
  16 |     |             // Get a location of some free memory and store it in tempBytes as
  17 |     |             // Solidity does for memory variables.
  18 |     |             tempBytes := mload(0x40)
  19 |     | 
  20 |     |             // Store the length of the first bytes array at the beginning of
  21 |     |             // the memory for tempBytes.
  22 |     |             let length := mload(_preBytes)
  23 |     |             mstore(tempBytes, length)
  24 |     | 
  25 |     |             // Maintain a memory counter for the current write location in the
  26 |     |             // temp bytes array by adding the 32 bytes for the array length to
  27 |     |             // the starting location.
  28 |     |             let mc := add(tempBytes, 0x20)
  29 |     |             // Stop copying when the memory counter reaches the length of the
  30 |     |             // first bytes array.
  31 |     |             let end := add(mc, length)
  32 |     | 
  33 |     |             for {
  34 |     |                 // Initialize a copy counter to the start of the _preBytes data,
  35 |     |                 // 32 bytes into its memory.
  36 |     |                 let cc := add(_preBytes, 0x20)
  37 |     |             } lt(mc, end) {
  38 |     |                 // Increase both counters by 32 bytes each iteration.
  39 |     |                 mc := add(mc, 0x20)
  40 |     |                 cc := add(cc, 0x20)
  41 |     |             } {
  42 |     |                 // Write the _preBytes data into the tempBytes memory 32 bytes
  43 |     |                 // at a time.
  44 |     |                 mstore(mc, mload(cc))
  45 |     |             }
  46 |     | 
  47 |     |             // Add the length of _postBytes to the current length of tempBytes
  48 |     |             // and store it as the new length in the first 32 bytes of the
  49 |     |             // tempBytes memory.
  50 |     |             length := mload(_postBytes)
  51 |     |             mstore(tempBytes, add(length, mload(tempBytes)))
  52 |     | 
  53 |     |             // Move the memory counter back from a multiple of 0x20 to the
  54 |     |             // actual end of the _preBytes data.
  55 |     |             mc := end
  56 |     |             // Stop copying when the memory counter reaches the new combined
  57 |     |             // length of the arrays.
  58 |     |             end := add(mc, length)
  59 |     | 
  60 |     |             for { let cc := add(_postBytes, 0x20) } lt(mc, end) {
  61 |     |                 mc := add(mc, 0x20)
  62 |     |                 cc := add(cc, 0x20)
  63 |     |             } { mstore(mc, mload(cc)) }
  64 |     | 
  65 |     |             // Update the free-memory pointer by padding our last write location
  66 |     |             // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
  67 |     |             // next 32 byte block, then round down to the nearest multiple of
  68 |     |             // 32. If the sum of the length of the two arrays is zero then add
  69 |     |             // one before rounding down to leave a blank 32 bytes (the length block with 0).
  70 |     |             mstore(
  71 |     |                 0x40,
  72 |     |                 and(
  73 |     |                     add(add(end, iszero(add(length, mload(_preBytes)))), 31),
  74 |     |                     not(31) // Round down to the nearest 32 bytes.
  75 |     |                 )
  76 |     |             )
  77 |     |         }
  78 |     | 
  79 |     |         return tempBytes;
  80 |     |     }
  81 |     | 
  82 |     |     function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
  83 |     |         assembly {
  84 |     |             // Read the first 32 bytes of _preBytes storage, which is the length
  85 |     |             // of the array. (We don't need to use the offset into the slot
  86 |     |             // because arrays use the entire slot.)
  87 |     |             let fslot := sload(_preBytes.slot)
  88 |     |             // Arrays of 31 bytes or less have an even value in their slot,
  89 |     |             // while longer arrays have an odd value. The actual length is
  90 |     |             // the slot divided by two for odd values, and the lowest order
  91 |     |             // byte divided by two for even values.
  92 |     |             // If the slot is even, bitwise and the slot with 255 and divide by
  93 |     |             // two to get the length. If the slot is odd, bitwise and the slot
  94 |     |             // with -1 and divide by two.
  95 |     |             let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
  96 |     |             let mlength := mload(_postBytes)
  97 |     |             let newlength := add(slength, mlength)
  98 |     |             // slength can contain both the length and contents of the array
  99 |     |             // if length < 32 bytes so let's prepare for that
 100 |     |             // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
 101 |     |             switch add(lt(slength, 32), lt(newlength, 32))
 102 |     |             case 2 {
 103 |     |                 // Since the new array still fits in the slot, we just need to
 104 |     |                 // update the contents of the slot.
 105 |     |                 // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
 106 |     |                 sstore(
 107 |     |                     _preBytes.slot,
 108 |     |                     // all the modifications to the slot are inside this
 109 |     |                     // next block
 110 |     |                     add(
 111 |     |                         // we can just add to the slot contents because the
 112 |     |                         // bytes we want to change are the LSBs
 113 |     |                         fslot,
 114 |     |                         add(
 115 |     |                             mul(
 116 |     |                                 div(
 117 |     |                                     // load the bytes from memory
 118 |     |                                     mload(add(_postBytes, 0x20)),
 119 |     |                                     // zero all bytes to the right
 120 |     |                                     exp(0x100, sub(32, mlength))
 121 |     |                                 ),
 122 |     |                                 // and now shift left the number of bytes to
 123 |     |                                 // leave space for the length in the slot
 124 |     |                                 exp(0x100, sub(32, newlength))
 125 |     |                             ),
 126 |     |                             // increase length by the double of the memory
 127 |     |                             // bytes length
 128 |     |                             mul(mlength, 2)
 129 |     |                         )
 130 |     |                     )
 131 |     |                 )
 132 |     |             }
 133 |     |             case 1 {
 134 |     |                 // The stored value fits in the slot, but the combined value
 135 |     |                 // will exceed it.
 136 |     |                 // get the keccak hash to get the contents of the array
 137 |     |                 mstore(0x0, _preBytes.slot)
 138 |     |                 let sc := add(keccak256(0x0, 0x20), div(slength, 32))
 139 |     | 
 140 |     |                 // save new length
 141 |     |                 sstore(_preBytes.slot, add(mul(newlength, 2), 1))
 142 |     | 
 143 |     |                 // The contents of the _postBytes array start 32 bytes into
 144 |     |                 // the structure. Our first read should obtain the `submod`
 145 |     |                 // bytes that can fit into the unused space in the last word
 146 |     |                 // of the stored array. To get this, we read 32 bytes starting
 147 |     |                 // from `submod`, so the data we read overlaps with the array
 148 |     |                 // contents by `submod` bytes. Masking the lowest-order
 149 |     |                 // `submod` bytes allows us to add that value directly to the
 150 |     |                 // stored value.
 151 |     | 
 152 |     |                 let submod := sub(32, slength)
 153 |     |                 let mc := add(_postBytes, submod)
 154 |     |                 let end := add(_postBytes, mlength)
 155 |     |                 let mask := sub(exp(0x100, submod), 1)
 156 |     | 
 157 |     |                 sstore(
 158 |     |                     sc,
 159 |     |                     add(
 160 |     |                         and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00),
 161 |     |                         and(mload(mc), mask)
 162 |     |                     )
 163 |     |                 )
 164 |     | 
 165 |     |                 for {
 166 |     |                     mc := add(mc, 0x20)
 167 |     |                     sc := add(sc, 1)
 168 |     |                 } lt(mc, end) {
 169 |     |                     sc := add(sc, 1)
 170 |     |                     mc := add(mc, 0x20)
 171 |     |                 } { sstore(sc, mload(mc)) }
 172 |     | 
 173 |     |                 mask := exp(0x100, sub(mc, end))
 174 |     | 
 175 |     |                 sstore(sc, mul(div(mload(mc), mask), mask))
 176 |     |             }
 177 |     |             default {
 178 |     |                 // get the keccak hash to get the contents of the array
 179 |     |                 mstore(0x0, _preBytes.slot)
 180 |     |                 // Start copying to the last used word of the stored array.
 181 |     |                 let sc := add(keccak256(0x0, 0x20), div(slength, 32))
 182 |     | 
 183 |     |                 // save new length
 184 |     |                 sstore(_preBytes.slot, add(mul(newlength, 2), 1))
 185 |     | 
 186 |     |                 // Copy over the first `submod` bytes of the new data as in
 187 |     |                 // case 1 above.
 188 |     |                 let slengthmod := mod(slength, 32)
 189 |     |                 let mlengthmod := mod(mlength, 32)
 190 |     |                 let submod := sub(32, slengthmod)
 191 |     |                 let mc := add(_postBytes, submod)
 192 |     |                 let end := add(_postBytes, mlength)
 193 |     |                 let mask := sub(exp(0x100, submod), 1)
 194 |     | 
 195 |     |                 sstore(sc, add(sload(sc), and(mload(mc), mask)))
 196 |     | 
 197 |     |                 for {
 198 |     |                     sc := add(sc, 1)
 199 |     |                     mc := add(mc, 0x20)
 200 |     |                 } lt(mc, end) {
 201 |     |                     sc := add(sc, 1)
 202 |     |                     mc := add(mc, 0x20)
 203 |     |                 } { sstore(sc, mload(mc)) }
 204 |     | 
 205 |     |                 mask := exp(0x100, sub(mc, end))
 206 |     | 
 207 |     |                 sstore(sc, mul(div(mload(mc), mask), mask))
 208 |     |             }
 209 |     |         }
 210 |     |     }
 211 |     | 
 212 |     |     function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {
 213 |     |         // We're using the unchecked block below because otherwise execution ends
 214 |     |         // with the native overflow error code.
 215 |     |         unchecked {
 216 |     |             require(_length + 31 >= _length, "slice_overflow");
 217 |     |         }
 218 |     |         require(_bytes.length >= _start + _length, "slice_outOfBounds");
 219 |     | 
 220 |     |         bytes memory tempBytes;
 221 |     | 
 222 |     |         assembly {
 223 |     |             switch iszero(_length)
 224 |     |             case 0 {
 225 |     |                 // Get a location of some free memory and store it in tempBytes as
 226 |     |                 // Solidity does for memory variables.
 227 |     |                 tempBytes := mload(0x40)
 228 |     | 
 229 |     |                 // The first word of the slice result is potentially a partial
 230 |     |                 // word read from the original array. To read it, we calculate
 231 |     |                 // the length of that partial word and start copying that many
 232 |     |                 // bytes into the array. The first word we copy will start with
 233 |     |                 // data we don't care about, but the last `lengthmod` bytes will
 234 |     |                 // land at the beginning of the contents of the new array. When
 235 |     |                 // we're done copying, we overwrite the full first word with
 236 |     |                 // the actual length of the slice.
 237 |     |                 let lengthmod := and(_length, 31)
 238 |     | 
 239 |     |                 // The multiplication in the next line is necessary
 240 |     |                 // because when slicing multiples of 32 bytes (lengthmod == 0)
 241 |     |                 // the following copy loop was copying the origin's length
 242 |     |                 // and then ending prematurely not copying everything it should.
 243 |     |                 let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
 244 |     |                 let end := add(mc, _length)
 245 |     | 
 246 |     |                 for {
 247 |     |                     // The multiplication in the next line has the same exact purpose
 248 |     |                     // as the one above.
 249 |     |                     let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
 250 |     |                 } lt(mc, end) {
 251 |     |                     mc := add(mc, 0x20)
 252 |     |                     cc := add(cc, 0x20)
 253 |     |                 } { mstore(mc, mload(cc)) }
 254 |     | 
 255 |     |                 mstore(tempBytes, _length)
 256 |     | 
 257 |     |                 //update free-memory pointer
 258 |     |                 //allocating the array padded to 32 bytes like the compiler does now
 259 |     |                 mstore(0x40, and(add(mc, 31), not(31)))
 260 |     |             }
 261 |     |             //if we want a zero-length slice let's just return a zero-length array
 262 |     |             default {
 263 |     |                 tempBytes := mload(0x40)
 264 |     |                 //zero out the 32 bytes slice we are about to return
 265 |     |                 //we need to do it because Solidity does not garbage collect
 266 |     |                 mstore(tempBytes, 0)
 267 |     | 
 268 |     |                 mstore(0x40, add(tempBytes, 0x20))
 269 |     |             }
 270 |     |         }
 271 |     | 
 272 |     |         return tempBytes;
 273 |     |     }
 274 |     | 
 275 | *   |     function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
 276 | *   |         require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
 277 |     |         address tempAddress;
 278 |     | 
 279 |     |         assembly {
 280 | *   |             tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
 281 |     |         }
 282 |     | 
 283 |     |         return tempAddress;
 284 |     |     }
 285 |     | 
 286 |     |     function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
 287 |     |         require(_bytes.length >= _start + 1, "toUint8_outOfBounds");
 288 |     |         uint8 tempUint;
 289 |     | 
 290 |     |         assembly {
 291 |     |             tempUint := mload(add(add(_bytes, 0x1), _start))
 292 |     |         }
 293 |     | 
 294 |     |         return tempUint;
 295 |     |     }
 296 |     | 
 297 |     |     function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
 298 |     |         require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
 299 |     |         uint16 tempUint;
 300 |     | 
 301 |     |         assembly {
 302 |     |             tempUint := mload(add(add(_bytes, 0x2), _start))
 303 |     |         }
 304 |     | 
 305 |     |         return tempUint;
 306 |     |     }
 307 |     | 
 308 |     |     function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
 309 |     |         require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
 310 |     |         uint32 tempUint;
 311 |     | 
 312 |     |         assembly {
 313 |     |             tempUint := mload(add(add(_bytes, 0x4), _start))
 314 |     |         }
 315 |     | 
 316 |     |         return tempUint;
 317 |     |     }
 318 |     | 
 319 |     |     function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
 320 |     |         require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
 321 |     |         uint64 tempUint;
 322 |     | 
 323 |     |         assembly {
 324 |     |             tempUint := mload(add(add(_bytes, 0x8), _start))
 325 |     |         }
 326 |     | 
 327 |     |         return tempUint;
 328 |     |     }
 329 |     | 
 330 |     |     function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
 331 |     |         require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
 332 |     |         uint96 tempUint;
 333 |     | 
 334 |     |         assembly {
 335 |     |             tempUint := mload(add(add(_bytes, 0xc), _start))
 336 |     |         }
 337 |     | 
 338 |     |         return tempUint;
 339 |     |     }
 340 |     | 
 341 |     |     function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
 342 |     |         require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
 343 |     |         uint128 tempUint;
 344 |     | 
 345 |     |         assembly {
 346 |     |             tempUint := mload(add(add(_bytes, 0x10), _start))
 347 |     |         }
 348 |     | 
 349 |     |         return tempUint;
 350 |     |     }
 351 |     | 
 352 | *   |     function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
 353 | *   |         require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
 354 |     |         uint256 tempUint;
 355 |     | 
 356 |     |         assembly {
 357 | *   |             tempUint := mload(add(add(_bytes, 0x20), _start))
 358 |     |         }
 359 |     | 
 360 |     |         return tempUint;
 361 |     |     }
 362 |     | 
 363 |     |     function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
 364 |     |         require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
 365 |     |         bytes32 tempBytes32;
 366 |     | 
 367 |     |         assembly {
 368 |     |             tempBytes32 := mload(add(add(_bytes, 0x20), _start))
 369 |     |         }
 370 |     | 
 371 |     |         return tempBytes32;
 372 |     |     }
 373 |     | 
 374 |     |     function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
 375 |     |         bool success = true;
 376 |     | 
 377 |     |         assembly {
 378 |     |             let length := mload(_preBytes)
 379 |     | 
 380 |     |             // if lengths don't match the arrays are not equal
 381 |     |             switch eq(length, mload(_postBytes))
 382 |     |             case 1 {
 383 |     |                 // cb is a circuit breaker in the for loop since there's
 384 |     |                 //  no said feature for inline assembly loops
 385 |     |                 // cb = 1 - don't breaker
 386 |     |                 // cb = 0 - break
 387 |     |                 let cb := 1
 388 |     | 
 389 |     |                 let mc := add(_preBytes, 0x20)
 390 |     |                 let end := add(mc, length)
 391 |     | 
 392 |     |                 for { let cc := add(_postBytes, 0x20) }
 393 |     |                 // the next line is the loop condition:
 394 |     |                 // while(uint256(mc < end) + cb == 2)
 395 |     |                 eq(add(lt(mc, end), cb), 2) {
 396 |     |                     mc := add(mc, 0x20)
 397 |     |                     cc := add(cc, 0x20)
 398 |     |                 } {
 399 |     |                     // if any of these checks fails then arrays are not equal
 400 |     |                     if iszero(eq(mload(mc), mload(cc))) {
 401 |     |                         // unsuccess:
 402 |     |                         success := 0
 403 |     |                         cb := 0
 404 |     |                     }
 405 |     |                 }
 406 |     |             }
 407 |     |             default {
 408 |     |                 // unsuccess:
 409 |     |                 success := 0
 410 |     |             }
 411 |     |         }
 412 |     | 
 413 |     |         return success;
 414 |     |     }
 415 |     | 
 416 |     |     function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {
 417 |     |         bool success = true;
 418 |     | 
 419 |     |         assembly {
 420 |     |             // we know _preBytes_offset is 0
 421 |     |             let fslot := sload(_preBytes.slot)
 422 |     |             // Decode the length of the stored array like in concatStorage().
 423 |     |             let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
 424 |     |             let mlength := mload(_postBytes)
 425 |     | 
 426 |     |             // if lengths don't match the arrays are not equal
 427 |     |             switch eq(slength, mlength)
 428 |     |             case 1 {
 429 |     |                 // slength can contain both the length and contents of the array
 430 |     |                 // if length < 32 bytes so let's prepare for that
 431 |     |                 // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
 432 |     |                 if iszero(iszero(slength)) {
 433 |     |                     switch lt(slength, 32)
 434 |     |                     case 1 {
 435 |     |                         // blank the last byte which is the length
 436 |     |                         fslot := mul(div(fslot, 0x100), 0x100)
 437 |     | 
 438 |     |                         if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
 439 |     |                             // unsuccess:
 440 |     |                             success := 0
 441 |     |                         }
 442 |     |                     }
 443 |     |                     default {
 444 |     |                         // cb is a circuit breaker in the for loop since there's
 445 |     |                         //  no said feature for inline assembly loops
 446 |     |                         // cb = 1 - don't breaker
 447 |     |                         // cb = 0 - break
 448 |     |                         let cb := 1
 449 |     | 
 450 |     |                         // get the keccak hash to get the contents of the array
 451 |     |                         mstore(0x0, _preBytes.slot)
 452 |     |                         let sc := keccak256(0x0, 0x20)
 453 |     | 
 454 |     |                         let mc := add(_postBytes, 0x20)
 455 |     |                         let end := add(mc, mlength)
 456 |     | 
 457 |     |                         // the next line is the loop condition:
 458 |     |                         // while(uint256(mc < end) + cb == 2)
 459 |     |                         for { } eq(add(lt(mc, end), cb), 2) {
 460 |     |                             sc := add(sc, 1)
 461 |     |                             mc := add(mc, 0x20)
 462 |     |                         } {
 463 |     |                             if iszero(eq(sload(sc), mload(mc))) {
 464 |     |                                 // unsuccess:
 465 |     |                                 success := 0
 466 |     |                                 cb := 0
 467 |     |                             }
 468 |     |                         }
 469 |     |                     }
 470 |     |                 }
 471 |     |             }
 472 |     |             default {
 473 |     |                 // unsuccess:
 474 |     |                 success := 0
 475 |     |             }
 476 |     |         }
 477 |     | 
 478 |     |         return success;
 479 |     |     }
 480 |     | }
 481 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/vendor/awesome-oracles/IOracle.sol
  1 |     | // SPDX-License-Identifier: UNLICENSED
  2 |     | pragma solidity ^0.8.20;
  3 |     | 
  4 |     | /// @title Common interface for price oracles.
  5 |     | /// @dev Implements the spec at https://eips.ethereum.org/EIPS/eip-7726
  6 |     | interface IOracle {
  7 |     |     /// @notice The oracle does not support the given base/quote pair.
  8 |     |     /// @param base The asset that the user needs to know the value or price for.
  9 |     |     /// @param quote The asset in which the user needs to value or price the base.
 10 |     |     error OracleUnsupportedPair(address base, address quote);
 11 |     | 
 12 |     |     /// @notice The oracle is not capable to provide data within a degree of confidence.
 13 |     |     /// @param base The asset that the user needs to know the value or price for.
 14 |     |     /// @param quote The asset in which the user needs to value or price the base.
 15 |     |     error OracleUntrustedData(address base, address quote);
 16 |     | 
 17 |     |     /// @notice Returns the value of `baseAmount` of `base` in `quote` terms.
 18 |     |     /// @dev MUST round down towards 0.
 19 |     |     /// MUST revert with `OracleUnsupportedPair` if not capable to provide data for the specified `base` and `quote`
 20 |     |     /// pair.
 21 |     |     /// MUST revert with `OracleUntrustedData` if not capable to provide data within a degree of confidence publicly
 22 |     |     /// specified.
 23 |     |     /// @param baseAmount The amount of `base` to convert.
 24 |     |     /// @param base The asset that the user needs to know the value for.
 25 |     |     /// @param quote The asset in which the user needs to value the base.
 26 |     |     /// @return quoteAmount The value of `baseAmount` of `base` in `quote` terms
 27 |     |     function getQuote(uint256 baseAmount, address base, address quote) external view returns (uint256 quoteAmount);
 28 |     | }
 29 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/vendor/pendle/IStandardizedYield.sol
   1 |     | // SPDX-License-Identifier: GPL-3.0-or-later
   2 |     | /*
   3 |     |  * MIT License
   4 |     |  * ===========
   5 |     |  *
   6 |     |  * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 |     |  * of this software and associated documentation files (the "Software"), to deal
   8 |     |  * in the Software without restriction, including without limitation the rights
   9 |     |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 |     |  * copies of the Software, and to permit persons to whom the Software is
  11 |     |  * furnished to do so, subject to the following conditions:
  12 |     |  *
  13 |     |  * The above copyright notice and this permission notice shall be included in all
  14 |     |  * copies or substantial portions of the Software.
  15 |     |  *
  16 |     |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 |     |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 |     |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 |     |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 |     |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 |     |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22 |     |  */
  23 |     | 
  24 |     | pragma solidity ^0.8.0;
  25 |     | 
  26 |     | import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
  27 |     | 
  28 |     | interface IStandardizedYield is IERC20Metadata {
  29 |     |     /// @dev Emitted when any base tokens is deposited to mint shares
  30 |     |     event Deposit(
  31 |     |         address indexed caller,
  32 |     |         address indexed receiver,
  33 |     |         address indexed tokenIn,
  34 |     |         uint256 amountDeposited,
  35 |     |         uint256 amountSyOut
  36 |     |     );
  37 |     | 
  38 |     |     /// @dev Emitted when any shares are redeemed for base tokens
  39 |     |     event Redeem(
  40 |     |         address indexed caller,
  41 |     |         address indexed receiver,
  42 |     |         address indexed tokenOut,
  43 |     |         uint256 amountSyToRedeem,
  44 |     |         uint256 amountTokenOut
  45 |     |     );
  46 |     | 
  47 |     |     /// @dev check `assetInfo()` for more information
  48 |     |     enum AssetType {
  49 |     |         TOKEN,
  50 |     |         LIQUIDITY
  51 |     |     }
  52 |     | 
  53 |     |     /// @dev Emitted when (`user`) claims their rewards
  54 |     |     event ClaimRewards(address indexed user, address[] rewardTokens, uint256[] rewardAmounts);
  55 |     | 
  56 |     |     /**
  57 |     |      * @notice mints an amount of shares by depositing a base token.
  58 |     |      * @param receiver shares recipient address
  59 |     |      * @param tokenIn address of the base tokens to mint shares
  60 |     |      * @param amountTokenToDeposit amount of base tokens to be transferred from (`msg.sender`)
  61 |     |      * @param minSharesOut reverts if amount of shares minted is lower than this
  62 |     |      * @return amountSharesOut amount of shares minted
  63 |     |      * @dev Emits a {Deposit} event
  64 |     |      *
  65 |     |      * Requirements:
  66 |     |      * - (`tokenIn`) must be a valid base token.
  67 |     |      */
  68 |     |     function deposit(
  69 |     |         address receiver,
  70 |     |         address tokenIn,
  71 |     |         uint256 amountTokenToDeposit,
  72 |     |         uint256 minSharesOut
  73 |     |     )
  74 |     |         external
  75 |     |         payable
  76 |     |         returns (uint256 amountSharesOut);
  77 |     | 
  78 |     |     /**
  79 |     |      * @notice redeems an amount of base tokens by burning some shares
  80 |     |      * @param receiver recipient address
  81 |     |      * @param amountSharesToRedeem amount of shares to be burned
  82 |     |      * @param tokenOut address of the base token to be redeemed
  83 |     |      * @param minTokenOut reverts if amount of base token redeemed is lower than this
  84 |     |      * @param burnFromInternalBalance if true, burns from balance of `address(this)`, otherwise burns from `msg.sender`
  85 |     |      * @return amountTokenOut amount of base tokens redeemed
  86 |     |      * @dev Emits a {Redeem} event
  87 |     |      *
  88 |     |      * Requirements:
  89 |     |      * - (`tokenOut`) must be a valid base token.
  90 |     |      */
  91 |     |     function redeem(
  92 |     |         address receiver,
  93 |     |         uint256 amountSharesToRedeem,
  94 |     |         address tokenOut,
  95 |     |         uint256 minTokenOut,
  96 |     |         bool burnFromInternalBalance
  97 |     |     )
  98 |     |         external
  99 |     |         returns (uint256 amountTokenOut);
 100 |     | 
 101 |     |     /**
 102 |     |      * @notice exchangeRate * syBalance / 1e18 must return the asset balance of the account
 103 |     |      * @notice vice-versa, if a user uses some amount of tokens equivalent to X asset, the amount of sy
 104 |     |      *  he can mint must be X * exchangeRate / 1e18
 105 |     |      * @dev SYUtils's assetToSy & syToAsset should be used instead of raw multiplication
 106 |     |      *  & division
 107 |     |      */
 108 |     |     function exchangeRate() external view returns (uint256 res);
 109 |     | 
 110 |     |     /**
 111 |     |      * @notice claims reward for (`user`)
 112 |     |      * @param user the user receiving their rewards
 113 |     |      * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens`
 114 |     |      * @dev
 115 |     |      * Emits a `ClaimRewards` event
 116 |     |      * See {getRewardTokens} for list of reward tokens
 117 |     |      */
 118 |     |     function claimRewards(address user) external returns (uint256[] memory rewardAmounts);
 119 |     | 
 120 |     |     /**
 121 |     |      * @notice get the amount of unclaimed rewards for (`user`)
 122 |     |      * @param user the user to check for
 123 |     |      * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens`
 124 |     |      */
 125 |     |     function accruedRewards(address user) external view returns (uint256[] memory rewardAmounts);
 126 |     | 
 127 |     |     function rewardIndexesCurrent() external returns (uint256[] memory indexes);
 128 |     | 
 129 |     |     function rewardIndexesStored() external view returns (uint256[] memory indexes);
 130 |     | 
 131 |     |     /**
 132 |     |      * @notice returns the list of reward token addresses
 133 |     |      */
 134 |     |     function getRewardTokens() external view returns (address[] memory);
 135 |     | 
 136 |     |     /**
 137 |     |      * @notice returns the address of the underlying yield token
 138 |     |      */
 139 |     |     function yieldToken() external view returns (address);
 140 |     | 
 141 |     |     /**
 142 |     |      * @notice returns all tokens that can mint this SY
 143 |     |      */
 144 |     |     function getTokensIn() external view returns (address[] memory res);
 145 |     | 
 146 |     |     /**
 147 |     |      * @notice returns all tokens that can be redeemed by this SY
 148 |     |      */
 149 |     |     function getTokensOut() external view returns (address[] memory res);
 150 |     | 
 151 |     |     function isValidTokenIn(address token) external view returns (bool);
 152 |     | 
 153 |     |     function isValidTokenOut(address token) external view returns (bool);
 154 |     | 
 155 |     |     function previewDeposit(
 156 |     |         address tokenIn,
 157 |     |         uint256 amountTokenToDeposit
 158 |     |     )
 159 |     |         external
 160 |     |         view
 161 |     |         returns (uint256 amountSharesOut);
 162 |     | 
 163 |     |     function previewRedeem(
 164 |     |         address tokenOut,
 165 |     |         uint256 amountSharesToRedeem
 166 |     |     )
 167 |     |         external
 168 |     |         view
 169 |     |         returns (uint256 amountTokenOut);
 170 |     | 
 171 |     |     /**
 172 |     |      * @notice This function contains information to interpret what the asset is
 173 |     |      * @return assetType the type of the asset (0 for ERC20 tokens, 1 for AMM liquidity tokens,
 174 |     |      *     2 for bridged yield bearing tokens like wstETH, rETH on Arbi whose the underlying asset doesn't exist on the
 175 |     |      * chain)
 176 |     |      * @return assetAddress the address of the asset
 177 |     |      * @return assetDecimals the decimals of the asset
 178 |     |      */
 179 |     |     function assetInfo() external view returns (AssetType assetType, address assetAddress, uint8 assetDecimals);
 180 |     | }
 181 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/vendor/standards/ERC7540/IERC7540Vault.sol
   1 |     | // SPDX-License-Identifier: AGPL-3.0-only
   2 |     | pragma solidity >=0.8.0;
   3 |     | 
   4 |     | import { IERC7741 } from "../ERC7741/IERC7741.sol";
   5 |     | 
   6 |     | interface IERC7540Operator {
   7 |     |     /**
   8 |     |      * @dev The event emitted when an operator is set.
   9 |     |      *
  10 |     |      * @param controller The address of the controller.
  11 |     |      * @param operator The address of the operator.
  12 |     |      * @param approved The approval status.
  13 |     |      */
  14 |     |     event OperatorSet(address indexed controller, address indexed operator, bool approved);
  15 |     | 
  16 |     |     /**
  17 |     |      * @dev Sets or removes an operator for the caller.
  18 |     |      *
  19 |     |      * @param operator The address of the operator.
  20 |     |      * @param approved The approval status.
  21 |     |      * @return Whether the call was executed successfully or not
  22 |     |      */
  23 |     |     function setOperator(address operator, bool approved) external returns (bool);
  24 |     | 
  25 |     |     /**
  26 |     |      * @dev Returns `true` if the `operator` is approved as an operator for an `controller`.
  27 |     |      *
  28 |     |      * @param controller The address of the controller.
  29 |     |      * @param operator The address of the operator.
  30 |     |      * @return status The approval status
  31 |     |      */
  32 |     |     function isOperator(address controller, address operator) external view returns (bool status);
  33 |     | }
  34 |     | 
  35 |     | interface IERC7540Deposit is IERC7540Operator {
  36 |     |     event DepositRequest(
  37 |     |         address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
  38 |     |     );
  39 |     |     /**
  40 |     |      * @dev Transfers assets from sender into the Vault and submits a Request for asynchronous deposit.
  41 |     |      *
  42 |     |      * - MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow.
  43 |     |      * - MUST revert if all of assets cannot be requested for deposit.
  44 |     |      * - owner MUST be msg.sender unless some unspecified explicit approval is given by the caller,
  45 |     |      *    approval of ERC-20 tokens from owner to sender is NOT enough.
  46 |     |      *
  47 |     |      * @param assets the amount of deposit assets to transfer from owner
  48 |     |      * @param controller the controller of the request who will be able to operate the request
  49 |     |      * @param owner the source of the deposit assets
  50 |     |      *
  51 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.
  52 |     |      */
  53 |     | 
  54 |     |     function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);
  55 |     | 
  56 |     |     /**
  57 |     |      * @dev Returns the amount of requested assets in Pending state.
  58 |     |      *
  59 |     |      * - MUST NOT include any assets in Claimable state for deposit or mint.
  60 |     |      * - MUST NOT show any variations depending on the caller.
  61 |     |      * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
  62 |     |      */
  63 |     |     function pendingDepositRequest(
  64 |     |         uint256 requestId,
  65 |     |         address controller
  66 |     |     )
  67 |     |         external
  68 |     |         view
  69 |     |         returns (uint256 pendingAssets);
  70 |     | 
  71 |     |     /**
  72 |     |      * @dev Returns the amount of requested assets in Claimable state for the controller to deposit or mint.
  73 |     |      *
  74 |     |      * - MUST NOT include any assets in Pending state.
  75 |     |      * - MUST NOT show any variations depending on the caller.
  76 |     |      * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
  77 |     |      */
  78 |     |     function claimableDepositRequest(
  79 |     |         uint256 requestId,
  80 |     |         address controller
  81 |     |     )
  82 |     |         external
  83 |     |         view
  84 |     |         returns (uint256 claimableAssets);
  85 |     | 
  86 |     |     /**
  87 |     |      * @dev Mints shares Vault shares to receiver by claiming the Request of the controller.
  88 |     |      *
  89 |     |      * - MUST emit the Deposit event.
  90 |     |      * - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
  91 |     |      */
  92 |     |     function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares);
  93 |     | 
  94 |     |     /**
  95 |     |      * @dev Mints exactly shares Vault shares to receiver by claiming the Request of the controller.
  96 |     |      *
  97 |     |      * - MUST emit the Deposit event.
  98 |     |      * - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
  99 |     |      */
 100 |     |     function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets);
 101 |     | }
 102 |     | 
 103 |     | interface IERC7540Redeem is IERC7540Operator {
 104 |     |     event RedeemRequest(
 105 |     |         address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
 106 |     |     );
 107 |     | 
 108 |     |     /**
 109 |     |      * @dev Assumes control of shares from sender into the Vault and submits a Request for asynchronous redeem.
 110 |     |      *
 111 |     |      * - MUST support a redeem Request flow where the control of shares is taken from sender directly
 112 |     |      *   where msg.sender has ERC-20 approval over the shares of owner.
 113 |     |      * - MUST revert if all of shares cannot be requested for redeem.
 114 |     |      *
 115 |     |      * @param shares the amount of shares to be redeemed to transfer from owner
 116 |     |      * @param controller the controller of the request who will be able to operate the request
 117 |     |      * @param owner the source of the shares to be redeemed
 118 |     |      *
 119 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault's share token.
 120 |     |      */
 121 |     |     function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);
 122 |     | 
 123 |     |     /**
 124 |     |      * @dev Returns the amount of requested shares in Pending state.
 125 |     |      *
 126 |     |      * - MUST NOT include any shares in Claimable state for redeem or withdraw.
 127 |     |      * - MUST NOT show any variations depending on the caller.
 128 |     |      * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
 129 |     |      */
 130 |     |     function pendingRedeemRequest(
 131 |     |         uint256 requestId,
 132 |     |         address controller
 133 |     |     )
 134 |     |         external
 135 |     |         view
 136 |     |         returns (uint256 pendingShares);
 137 |     | 
 138 |     |     /**
 139 |     |      * @dev Returns the amount of requested shares in Claimable state for the controller to redeem or withdraw.
 140 |     |      *
 141 |     |      * - MUST NOT include any shares in Pending state for redeem or withdraw.
 142 |     |      * - MUST NOT show any variations depending on the caller.
 143 |     |      * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
 144 |     |      */
 145 |     |     function claimableRedeemRequest(
 146 |     |         uint256 requestId,
 147 |     |         address controller
 148 |     |     )
 149 |     |         external
 150 |     |         view
 151 |     |         returns (uint256 claimableShares);
 152 |     | }
 153 |     | 
 154 |     | interface IERC7540CancelDeposit {
 155 |     |     event CancelDepositRequest(address indexed controller, uint256 indexed requestId, address sender);
 156 |     |     event CancelDepositClaim(
 157 |     |         address indexed receiver, address indexed controller, uint256 indexed requestId, address sender, uint256 assets
 158 |     |     );
 159 |     | 
 160 |     |     /**
 161 |     |      * @dev Submits a Request for cancelling the pending deposit Request
 162 |     |      *
 163 |     |      * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
 164 |     |      *    approval of ERC-20 tokens from controller to sender is NOT enough.
 165 |     |      * - MUST set pendingCancelDepositRequest to `true` for the returned requestId after request
 166 |     |      * - MUST increase claimableCancelDepositRequest for the returned requestId after fulfillment
 167 |     |      * - SHOULD be claimable using `claimCancelDepositRequest`
 168 |     |      * Note: while `pendingCancelDepositRequest` is `true`, `requestDeposit` cannot be called
 169 |     |      */
 170 |     |     function cancelDepositRequest(uint256 requestId, address controller) external;
 171 |     | 
 172 |     |     /**
 173 |     |      * @dev Returns whether the deposit Request is pending cancelation
 174 |     |      *
 175 |     |      * - MUST NOT show any variations depending on the caller.
 176 |     |      */
 177 |     |     function pendingCancelDepositRequest(
 178 |     |         uint256 requestId,
 179 |     |         address controller
 180 |     |     )
 181 |     |         external
 182 |     |         view
 183 |     |         returns (bool isPending);
 184 |     | 
 185 |     |     /**
 186 |     |      * @dev Returns the amount of assets that were canceled from a deposit Request, and can now be claimed.
 187 |     |      *
 188 |     |      * - MUST NOT show any variations depending on the caller.
 189 |     |      */
 190 |     |     function claimableCancelDepositRequest(
 191 |     |         uint256 requestId,
 192 |     |         address controller
 193 |     |     )
 194 |     |         external
 195 |     |         view
 196 |     |         returns (uint256 claimableAssets);
 197 |     | 
 198 |     |     /**
 199 |     |      * @dev Claims the canceled deposit assets, and removes the pending cancelation Request
 200 |     |      *
 201 |     |      * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
 202 |     |      *    approval of ERC-20 tokens from controller to sender is NOT enough.
 203 |     |      * - MUST set pendingCancelDepositRequest to `false` for the returned requestId after request
 204 |     |      * - MUST set claimableCancelDepositRequest to 0 for the returned requestId after fulfillment
 205 |     |      */
 206 |     |     function claimCancelDepositRequest(
 207 |     |         uint256 requestId,
 208 |     |         address receiver,
 209 |     |         address controller
 210 |     |     )
 211 |     |         external
 212 |     |         returns (uint256 assets);
 213 |     | }
 214 |     | 
 215 |     | interface IERC7540CancelRedeem {
 216 |     |     event CancelRedeemRequest(address indexed controller, uint256 indexed requestId, address sender);
 217 |     |     event CancelRedeemClaim(
 218 |     |         address indexed receiver, address indexed controller, uint256 indexed requestId, address sender, uint256 shares
 219 |     |     );
 220 |     | 
 221 |     |     /**
 222 |     |      * @dev Submits a Request for cancelling the pending redeem Request
 223 |     |      *
 224 |     |      * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
 225 |     |      *    approval of ERC-20 tokens from controller to sender is NOT enough.
 226 |     |      * - MUST set pendingCancelRedeemRequest to `true` for the returned requestId after request
 227 |     |      * - MUST increase claimableCancelRedeemRequest for the returned requestId after fulfillment
 228 |     |      * - SHOULD be claimable using `claimCancelRedeemRequest`
 229 |     |      * Note: while `pendingCancelRedeemRequest` is `true`, `requestRedeem` cannot be called
 230 |     |      */
 231 |     |     function cancelRedeemRequest(uint256 requestId, address controller) external;
 232 |     | 
 233 |     |     /**
 234 |     |      * @dev Returns whether the redeem Request is pending cancelation
 235 |     |      *
 236 |     |      * - MUST NOT show any variations depending on the caller.
 237 |     |      */
 238 |     |     function pendingCancelRedeemRequest(uint256 requestId, address controller) external view returns (bool isPending);
 239 |     | 
 240 |     |     /**
 241 |     |      * @dev Returns the amount of shares that were canceled from a redeem Request, and can now be claimed.
 242 |     |      *
 243 |     |      * - MUST NOT show any variations depending on the caller.
 244 |     |      */
 245 |     |     function claimableCancelRedeemRequest(
 246 |     |         uint256 requestId,
 247 |     |         address controller
 248 |     |     )
 249 |     |         external
 250 |     |         view
 251 |     |         returns (uint256 claimableShares);
 252 |     | 
 253 |     |     /**
 254 |     |      * @dev Claims the canceled redeem shares, and removes the pending cancelation Request
 255 |     |      *
 256 |     |      * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
 257 |     |      *    approval of ERC-20 tokens from controller to sender is NOT enough.
 258 |     |      * - MUST set pendingCancelRedeemRequest to `false` for the returned requestId after request
 259 |     |      * - MUST set claimableCancelRedeemRequest to 0 for the returned requestId after fulfillment
 260 |     |      */
 261 |     |     function claimCancelRedeemRequest(
 262 |     |         uint256 requestId,
 263 |     |         address receiver,
 264 |     |         address controller
 265 |     |     )
 266 |     |         external
 267 |     |         returns (uint256 shares);
 268 |     | }
 269 |     | 
 270 |     | /**
 271 |     |  * @title  IERC7540
 272 |     |  * @dev    Fully async ERC7540 implementation according to the standard
 273 |     |  * @dev    Adapted from Centrifuge's IERC7540 implementation
 274 |     |  */
 275 |     | interface IERC7540 is IERC7540Deposit, IERC7540Redeem { }
 276 |     | 
 277 |     | /**
 278 |     |  * @title  IERC7540Vault
 279 |     |  * @dev    This is the specific set of interfaces used by the SuperVaults
 280 |     |  */
 281 |     | interface IERC7540Vault is IERC7540, IERC7741 {
 282 |     |     event DepositClaimable(address indexed controller, uint256 indexed requestId, uint256 assets, uint256 shares);
 283 |     |     event RedeemClaimable(address indexed controller, uint256 indexed requestId, uint256 assets, uint256 shares);
 284 |     | }
 285 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/vendor/standards/ERC7741/IERC7741.sol
  1 |     | // SPDX-License-Identifier: AGPL-3.0-only
  2 |     | pragma solidity >=0.8.0;
  3 |     | 
  4 |     | interface IERC7741 {
  5 |     |     /**
  6 |     |      * @dev Grants or revokes permissions for `operator` to manage Requests on behalf of the
  7 |     |      *      `msg.sender`, using an [EIP-712](./eip-712.md) signature.
  8 |     |      */
  9 |     |     function authorizeOperator(
 10 |     |         address controller,
 11 |     |         address operator,
 12 |     |         bool approved,
 13 |     |         bytes32 nonce,
 14 |     |         uint256 deadline,
 15 |     |         bytes memory signature
 16 |     |     )
 17 |     |         external
 18 |     |         returns (bool);
 19 |     | 
 20 |     |     /**
 21 |     |      * @dev Revokes the given `nonce` for `msg.sender` as the `owner`.
 22 |     |      */
 23 |     |     function invalidateNonce(bytes32 nonce) external;
 24 |     | 
 25 |     |     /**
 26 |     |      * @dev Returns whether the given `nonce` has been used for the `controller`.
 27 |     |      */
 28 |     |     function authorizations(address controller, bytes32 nonce) external view returns (bool used);
 29 |     | 
 30 |     |     /**
 31 |     |      * @dev Returns the `DOMAIN_SEPARATOR` as defined according to EIP-712. The `DOMAIN_SEPARATOR
 32 |     |      *      should be unique to the contract and chain to prevent replay attacks from other domains,
 33 |     |      *      and satisfy the requirements of EIP-712, but is otherwise unconstrained.
 34 |     |      */
 35 |     |     function DOMAIN_SEPARATOR() external view returns (bytes32);
 36 |     | }
 37 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/vendor/superform/ISuperVault.sol
  1 |     | // SPDX-License-Identifier: UNLICENSED
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | /// @title ISuperVault
  5 |     | /// @notice Interface for SuperVault core contract that manages share minting
  6 |     | /// @author Superform Labs
  7 |     | interface ISuperVault {
  8 |     |     /*//////////////////////////////////////////////////////////////
  9 |     |                                 ERRORS
 10 |     |     //////////////////////////////////////////////////////////////*/
 11 |     |     error ALREADY_INITIALIZED();
 12 |     |     error INVALID_ASSET();
 13 |     |     error INVALID_STRATEGY();
 14 |     |     error INVALID_ESCROW();
 15 |     |     error ZERO_ADDRESS();
 16 |     |     error ZERO_AMOUNT();
 17 |     |     error INVALID_OWNER_OR_OPERATOR();
 18 |     |     error INVALID_AMOUNT();
 19 |     |     error REQUEST_NOT_FOUND();
 20 |     |     error UNAUTHORIZED();
 21 |     |     error TIMELOCK_NOT_EXPIRED();
 22 |     |     error INVALID_SIGNATURE();
 23 |     |     error NOT_IMPLEMENTED();
 24 |     |     error INVALID_NONCE();
 25 |     |     error INVALID_WITHDRAW_PRICE();
 26 |     |     error TRANSFER_FAILED();
 27 |     |     error CAP_EXCEEDED();
 28 |     |     error INVALID_PPS();
 29 |     |     error INVALID_CONTROLLER();
 30 |     | 
 31 |     |     /*//////////////////////////////////////////////////////////////
 32 |     |                                 EVENTS
 33 |     |     //////////////////////////////////////////////////////////////*/
 34 |     | 
 35 |     |     event RedeemClaimable(
 36 |     |         address indexed user,
 37 |     |         uint256 indexed requestId,
 38 |     |         uint256 assets,
 39 |     |         uint256 shares,
 40 |     |         uint256 averageWithdrawPrice,
 41 |     |         uint256 accumulatorShares,
 42 |     |         uint256 accumulatorCostBasis
 43 |     |     );
 44 |     | 
 45 |     |     event NonceInvalidated(address indexed sender, bytes32 indexed nonce);
 46 |     | 
 47 |     |     event RedeemRequestCancelled(address indexed controller, address indexed sender);
 48 |     | 
 49 |     |     /*//////////////////////////////////////////////////////////////
 50 |     |                             EXTERNAL METHODS
 51 |     |     //////////////////////////////////////////////////////////////*/
 52 |     | 
 53 |     |     function cancelRedeem(address controller) external;
 54 |     | 
 55 |     |     /// @notice Mint new shares, only callable by strategy
 56 |     |     /// @param amount The amount of shares to mint
 57 |     |     function mintShares(uint256 amount) external;
 58 |     | 
 59 |     |     /// @notice Burn shares, only callable by strategy
 60 |     |     /// @param amount The amount of shares to burn
 61 |     |     function burnShares(uint256 amount) external;
 62 |     | 
 63 |     |     /// @notice Callback function for when a redeem becomes claimable
 64 |     |     /// @param user The user whose redeem is claimable
 65 |     |     /// @param assets The amount of assets to be received
 66 |     |     /// @param shares The amount of shares redeemed
 67 |     |     /// @param averageWithdrawPrice The average price of the redeem
 68 |     |     /// @param accumulatorShares The amount of shares in the accumulator
 69 |     |     /// @param accumulatorCostBasis The cost basis of the accumulator
 70 |     |     function onRedeemClaimable(
 71 |     |         address user,
 72 |     |         uint256 assets,
 73 |     |         uint256 shares,
 74 |     |         uint256 averageWithdrawPrice,
 75 |     |         uint256 accumulatorShares,
 76 |     |         uint256 accumulatorCostBasis
 77 |     |     )
 78 |     |         external;
 79 |     | }
 80 |     | 

/opt/scfuzzbench/work/target/lib/v2-core/src/vendor/vaults/7540/IERC7540.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | interface IERC7575 {
   5 |     |     event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
   6 |     |     event Withdraw(
   7 |     |         address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
   8 |     |     );
   9 |     | 
  10 |     |     /**
  11 |     |      * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
  12 |     |      *
  13 |     |      * - MUST be an ERC-20 token contract.
  14 |     |      * - MUST NOT revert.
  15 |     |      */
  16 |     |     function asset() external view returns (address assetTokenAddress);
  17 |     | 
  18 |     |     /**
  19 |     |      * @dev Returns the address of the share token
  20 |     |      *
  21 |     |      * - MUST be an ERC-20 token contract.
  22 |     |      * - MUST NOT revert.
  23 |     |      */
  24 |     |     function share() external view returns (address shareTokenAddress);
  25 |     | 
  26 |     |     /**
  27 |     |      * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
  28 |     |      * scenario where all the conditions are met.
  29 |     |      *
  30 |     |      * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
  31 |     |      * - MUST NOT show any variations depending on the caller.
  32 |     |      * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
  33 |     |      * - MUST NOT revert.
  34 |     |      *
  35 |     |      * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
  36 |     |      * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
  37 |     |      * from.
  38 |     |      */
  39 |     |     function convertToShares(uint256 assets) external view returns (uint256 shares);
  40 |     | 
  41 |     |     /**
  42 |     |      * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
  43 |     |      * scenario where all the conditions are met.
  44 |     |      *
  45 |     |      * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
  46 |     |      * - MUST NOT show any variations depending on the caller.
  47 |     |      * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
  48 |     |      * - MUST NOT revert.
  49 |     |      *
  50 |     |      * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
  51 |     |      * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
  52 |     |      * from.
  53 |     |      */
  54 |     |     function convertToAssets(uint256 shares) external view returns (uint256 assets);
  55 |     | 
  56 |     |     /**
  57 |     |      * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
  58 |     |      *
  59 |     |      * - SHOULD include any compounding that occurs from yield.
  60 |     |      * - MUST be inclusive of any fees that are charged against assets in the Vault.
  61 |     |      * - MUST NOT revert.
  62 |     |      */
  63 |     |     function totalAssets() external view returns (uint256 totalManagedAssets);
  64 |     | 
  65 |     |     /**
  66 |     |      * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
  67 |     |      * through a deposit call.
  68 |     |      *
  69 |     |      * - MUST return a limited value if receiver is subject to some deposit limit.
  70 |     |      * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
  71 |     |      * - MUST NOT revert.
  72 |     |      */
  73 |     |     function maxDeposit(address receiver) external view returns (uint256 maxAssets);
  74 |     | 
  75 |     |     /**
  76 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
  77 |     |      * current on-chain conditions.
  78 |     |      *
  79 |     |      * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
  80 |     |      *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
  81 |     |      *   in the same transaction.
  82 |     |      * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
  83 |     |      *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
  84 |     |      * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
  85 |     |      * - MUST NOT revert.
  86 |     |      *
  87 |     |      * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
  88 |     |      * share price or some other type of condition, meaning the depositor will lose assets by depositing.
  89 |     |      */
  90 |     |     function previewDeposit(uint256 assets) external view returns (uint256 shares);
  91 |     | 
  92 |     |     /**
  93 |     |      * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
  94 |     |      *
  95 |     |      * - MUST emit the Deposit event.
  96 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
  97 |     |      *   deposit execution, and are accounted for during deposit.
  98 |     |      * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
  99 |     |      *   approving enough underlying tokens to the Vault contract, etc).
 100 |     |      *
 101 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
 102 |     |      */
 103 |     |     function deposit(uint256 assets, address receiver) external returns (uint256 shares);
 104 |     | 
 105 |     |     /**
 106 |     |      * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
 107 |     |      * - MUST return a limited value if receiver is subject to some mint limit.
 108 |     |      * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
 109 |     |      * - MUST NOT revert.
 110 |     |      */
 111 |     |     function maxMint(address receiver) external view returns (uint256 maxShares);
 112 |     | 
 113 |     |     /**
 114 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
 115 |     |      * current on-chain conditions.
 116 |     |      *
 117 |     |      * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
 118 |     |      *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
 119 |     |      *   same transaction.
 120 |     |      * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
 121 |     |      *   would be accepted, regardless if the user has enough tokens approved, etc.
 122 |     |      * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
 123 |     |      * - MUST NOT revert.
 124 |     |      *
 125 |     |      * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
 126 |     |      * share price or some other type of condition, meaning the depositor will lose assets by minting.
 127 |     |      */
 128 |     |     function previewMint(uint256 shares) external view returns (uint256 assets);
 129 |     | 
 130 |     |     /**
 131 |     |      * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
 132 |     |      *
 133 |     |      * - MUST emit the Deposit event.
 134 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
 135 |     |      *   execution, and are accounted for during mint.
 136 |     |      * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
 137 |     |      *   approving enough underlying tokens to the Vault contract, etc).
 138 |     |      *
 139 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
 140 |     |      */
 141 |     |     function mint(uint256 shares, address receiver) external returns (uint256 assets);
 142 |     | 
 143 |     |     /**
 144 |     |      * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
 145 |     |      * Vault, through a withdraw call.
 146 |     |      *
 147 |     |      * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
 148 |     |      * - MUST NOT revert.
 149 |     |      */
 150 |     |     function maxWithdraw(address owner) external view returns (uint256 maxAssets);
 151 |     | 
 152 |     |     /**
 153 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
 154 |     |      * given current on-chain conditions.
 155 |     |      *
 156 |     |      * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
 157 |     |      *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
 158 |     |      *   called
 159 |     |      *   in the same transaction.
 160 |     |      * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
 161 |     |      *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
 162 |     |      * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
 163 |     |      * - MUST NOT revert.
 164 |     |      *
 165 |     |      * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
 166 |     |      * share price or some other type of condition, meaning the depositor will lose assets by depositing.
 167 |     |      */
 168 |     |     function previewWithdraw(uint256 assets) external view returns (uint256 shares);
 169 |     | 
 170 |     |     /**
 171 |     |      * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
 172 |     |      *
 173 |     |      * - MUST emit the Withdraw event.
 174 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
 175 |     |      *   withdraw execution, and are accounted for during withdraw.
 176 |     |      * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
 177 |     |      *   not having enough shares, etc).
 178 |     |      *
 179 |     |      * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
 180 |     |      * Those methods should be performed separately.
 181 |     |      */
 182 |     |     function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
 183 |     | 
 184 |     |     /**
 185 |     |      * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
 186 |     |      * through a redeem call.
 187 |     |      *
 188 |     |      * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
 189 |     |      * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
 190 |     |      * - MUST NOT revert.
 191 |     |      */
 192 |     |     function maxRedeem(address owner) external view returns (uint256 maxShares);
 193 |     | 
 194 |     |     /**
 195 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
 196 |     |      * given current on-chain conditions.
 197 |     |      *
 198 |     |      * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
 199 |     |      *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
 200 |     |      *   same transaction.
 201 |     |      * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
 202 |     |      *   redemption would be accepted, regardless if the user has enough shares, etc.
 203 |     |      * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
 204 |     |      * - MUST NOT revert.
 205 |     |      *
 206 |     |      * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
 207 |     |      * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
 208 |     |      */
 209 |     |     function previewRedeem(uint256 shares) external view returns (uint256 assets);
 210 |     | 
 211 |     |     /**
 212 |     |      * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
 213 |     |      *
 214 |     |      * - MUST emit the Withdraw event.
 215 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
 216 |     |      *   redeem execution, and are accounted for during redeem.
 217 |     |      * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
 218 |     |      *   not having enough shares, etc).
 219 |     |      *
 220 |     |      * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
 221 |     |      * Those methods should be performed separately.
 222 |     |      */
 223 |     |     function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
 224 |     | }
 225 |     | // As defined by https://eips.ethereum.org/EIPS/eip-7540#request-flows
 226 |     | 
 227 |     | interface IERC7540 is IERC7575 {
 228 |     |     event DepositRequest(
 229 |     |         address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
 230 |     |     );
 231 |     | 
 232 |     |     event RedeemRequest(
 233 |     |         address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
 234 |     |     );
 235 |     | 
 236 |     |     /*//////////////////////////////////////////////////////////////
 237 |     |                                  VIEW METHODS
 238 |     |     //////////////////////////////////////////////////////////////*/
 239 |     |     /// @notice Check if the contract supports an interface
 240 |     |     /// @param interfaceId The selector of the interface to check
 241 |     |     function supportsInterface(bytes4 interfaceId) external view returns (bool);
 242 |     | 
 243 |     |     /// @notice Preview the amount of assets that would be received for a given amount of shares
 244 |     |     /// @param shares The amount of shares to redeem
 245 |     |     function previewRedeem(uint256 shares) external view returns (uint256 assets);
 246 |     | 
 247 |     |     /// @notice Check if a deposit request is pending
 248 |     |     /// @param requestId The id of the request to check
 249 |     |     /// @param controller The address of the controller
 250 |     |     function pendingDepositRequest(uint256 requestId, address controller) external view returns (uint256);
 251 |     | 
 252 |     |     /// @notice Check if a deposit request is pending cancellation
 253 |     |     /// @param requestId The id of the request to check
 254 |     |     /// @param controller The address of the controller
 255 |     |     function pendingCancelDepositRequest(uint256 requestId, address controller) external view returns (bool);
 256 |     | 
 257 |     |     /// @notice Check if a redeem request is pending
 258 |     |     /// @param requestId The id of the request to check
 259 |     |     /// @param controller The address of the controller
 260 |     |     function pendingRedeemRequest(uint256 requestId, address controller) external view returns (uint256);
 261 |     | 
 262 |     |     /// @notice Get the amount of assets that can be claimed from a deposit request
 263 |     |     /// @param requestId The id of the request to check
 264 |     |     /// @param controller The address of the controller
 265 |     |     function claimableDepositRequest(uint256 requestId, address controller) external view returns (uint256);
 266 |     | 
 267 |     |     /// @notice Get the amount of shares that can be claimed from a redeem request
 268 |     |     /// @param requestId The id of the request to check
 269 |     |     /// @param controller The address of the controller
 270 |     |     function claimableRedeemRequest(uint256 requestId, address controller) external view returns (uint256);
 271 |     | 
 272 |     |     /// @notice Check if a redeem request is pending cancellation
 273 |     |     /// @param requestId The id of the request to check
 274 |     |     /// @param controller The address of the controller
 275 |     |     function pendingCancelRedeemRequest(uint256 requestId, address controller) external view returns (bool);
 276 |     | 
 277 |     |     /*//////////////////////////////////////////////////////////////
 278 |     |                                  EXTERNAL METHODS
 279 |     |     //////////////////////////////////////////////////////////////*/
 280 |     |     /// @notice Mints amount of shares by claiming the controller's request
 281 |     |     /// @dev sender must be the controller or an operator approved by the controller
 282 |     |     /// @param assets The amount of assets to deposit
 283 |     |     /// @param receiver The address of the receiver
 284 |     |     /// @param controller The address of the controller
 285 |     |     function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares);
 286 |     | 
 287 |     |     /// @notice Mint exact amount of shares into the vault by claiming the controller's request
 288 |     |     /// @param shares The amount of shares to mint
 289 |     |     /// @param receiver The address of the receiver
 290 |     |     /// @param controller The address of the controller
 291 |     |     function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets);
 292 |     | 
 293 |     |     /// @notice Burn shares from the vault and sends exact amount of assets to the receiver
 294 |     |     /// @param assets The amount of assets to withdraw
 295 |     |     /// @param receiver The address of the receiver
 296 |     |     /// @param owner The address of the owner
 297 |     |     function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
 298 |     | 
 299 |     |     /// @notice Burns exact shares from the vault and sends assets to the receiver
 300 |     |     /// @param shares The amount of shares to redeem
 301 |     |     /// @param receiver The address of the receiver
 302 |     |     /// @param owner The address of the owner
 303 |     |     function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
 304 |     | 
 305 |     |     /// @notice Request a deposit of assets
 306 |     |     /// @param assets The amount of assets to deposit
 307 |     |     /// @param controller The address of the controller
 308 |     |     /// @param owner The address of the owner
 309 |     |     function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);
 310 |     | 
 311 |     |     /// @notice Request a redeem of shares
 312 |     |     /// @param shares The amount of shares to redeem
 313 |     |     /// @param controller The address of the controller
 314 |     |     /// @param owner The address of the owner
 315 |     |     function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);
 316 |     | 
 317 |     |     /// @notice Cancel a deposit request
 318 |     |     /// @param requestId The id of the request to cancel
 319 |     |     /// @param controller The address of the controller
 320 |     |     function cancelDepositRequest(uint256 requestId, address controller) external;
 321 |     | 
 322 |     |     /// @notice Claims the canceled deposit assets, and removes the pending cancelation Request
 323 |     |     /// @dev sender must be the controller
 324 |     |     /// @param requestId The id of the request to claim
 325 |     |     /// @param receiver The address of the receiver
 326 |     |     /// @param controller The address of the controller
 327 |     |     function claimCancelDepositRequest(
 328 |     |         uint256 requestId,
 329 |     |         address receiver,
 330 |     |         address controller
 331 |     |     )
 332 |     |         external
 333 |     |         returns (uint256 assets);
 334 |     | 
 335 |     |     /// @notice Cancel a redeem request
 336 |     |     /// @param requestId The id of the request to cancel
 337 |     |     /// @param controller The address of the controller
 338 |     |     function cancelRedeemRequest(uint256 requestId, address controller) external;
 339 |     | 
 340 |     |     /// @notice Claims the canceled redeem shares, and removes the pending cancelation Request
 341 |     |     /// @dev sender must be the controller
 342 |     |     /// @param requestId The id of the request to claim
 343 |     |     /// @param receiver The address of the receiver
 344 |     |     /// @param controller The address of the controller
 345 |     |     function claimCancelRedeemRequest(
 346 |     |         uint256 requestId,
 347 |     |         address receiver,
 348 |     |         address controller
 349 |     |     )
 350 |     |         external
 351 |     |         returns (uint256 shares);
 352 |     | 
 353 |     |     /// @notice Get the pool id
 354 |     |     function poolId() external view returns (uint64);
 355 |     | 
 356 |     |     /// @notice Get the tranche id
 357 |     |     function trancheId() external view returns (bytes16);
 358 |     | 
 359 |     |     /*//////////////////////////////////////////////////////////////
 360 |     |                                  OWNER METHODS
 361 |     |     //////////////////////////////////////////////////////////////*/
 362 |     |     function setOperator(address operator, bool approved) external returns (bool);
 363 |     |     function isOperator(address controller, address operator) external view returns (bool status);
 364 |     | }
 365 |     | 

/opt/scfuzzbench/work/target/src/SuperGovernor.sol
    1 |     | // SPDX-License-Identifier: UNLICENSED
    2 |     | pragma solidity 0.8.30;
    3 |     | 
    4 |     | // external
    5 |     | import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
    6 |     | import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
    7 |     | import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
    8 |     | 
    9 |     | // Superform
   10 |     | import { ISuperGovernor, FeeType } from "./interfaces/ISuperGovernor.sol";
   11 |     | import { ISuperVaultAggregator } from "./interfaces/SuperVault/ISuperVaultAggregator.sol";
   12 |     | import { ISuperAssetFactory } from "./interfaces/SuperAsset/ISuperAssetFactory.sol";
   13 |     | import { ISuperOracle } from "./interfaces/oracles/ISuperOracle.sol";
   14 |     | import { ISuperOracleL2 } from "./interfaces/oracles/ISuperOracleL2.sol";
   15 |     | 
   16 |     | /// @title SuperGovernor
   17 |     | /// @author Superform Labs
   18 |     | /// @notice Central registry for all deployed contracts in the Superform periphery
   19 | *   | contract SuperGovernor is ISuperGovernor, AccessControl {
   20 |     |     using EnumerableSet for EnumerableSet.AddressSet;
   21 |     | 
   22 |     |     /*//////////////////////////////////////////////////////////////
   23 |     |                                  STORAGE
   24 |     |     //////////////////////////////////////////////////////////////*/
   25 |     |     // Address registry
   26 |     |     mapping(bytes32 id => address address_) private _addressRegistry;
   27 |     | 
   28 |     |     // PPS Oracle management
   29 |     |     // Active PPS Oracle quorum requirement
   30 |     |     uint256 private _activePPSOracleQuorum;
   31 |     |     // Current active PPS Oracle
   32 |     |     address private _activePPSOracle;
   33 |     |     // Proposed new active PPS Oracle
   34 |     |     address private _proposedActivePPSOracle;
   35 |     |     // Effective time for proposed active PPS Oracle change
   36 |     |     uint256 private _activePPSOracleEffectiveTime;
   37 |     | 
   38 |     |     // Hook registry
   39 |     |     EnumerableSet.AddressSet private _registeredHooks;
   40 |     |     EnumerableSet.AddressSet private _registeredFulfillRequestsHooks;
   41 |     | 
   42 |     |     // SuperBank Hook Target validation
   43 |     |     mapping(address hook => ISuperGovernor.HookMerkleRootData merkleData) private superBankHooksMerkleRoots;
   44 |     | 
   45 |     |     // VaultBank registry
   46 |     |     EnumerableSet.AddressSet private _vaultBanks;
   47 |     |     mapping(uint64 chainId => address vaultBank) private _vaultBanksByChainId;
   48 |     | 
   49 |     |     // VaultBank Hook Target validation
   50 |     |     mapping(address hook => ISuperGovernor.HookMerkleRootData merkleData) private vaultBankHooksMerkleRoots;
   51 |     | 
   52 |     |     // Global freeze for manager takeovers
   53 |     |     bool private _managerTakeoversFrozen;
   54 |     | 
   55 |     |     // Validator registry
   56 |     |     EnumerableSet.AddressSet private _validators;
   57 |     | 
   58 |     |     // Relayer registry
   59 |     |     EnumerableSet.AddressSet private _relayers;
   60 |     | 
   61 |     |     // Protected keepers registry (cannot be added as authorized callers by managers)
   62 |     |     EnumerableSet.AddressSet private _protectedKeepers;
   63 |     | 
   64 |     |     // Executor registry
   65 |     |     EnumerableSet.AddressSet private _executors;
   66 |     | 
   67 |     |     // Polymer prover
   68 |     |     address private _prover;
   69 |     | 
   70 |     |     // Whitelisted incentive tokens
   71 |     |     mapping(address token => bool isWhitelisted) private _isWhitelistedIncentiveToken;
   72 |     |     EnumerableSet.AddressSet private _proposedWhitelistedIncentiveTokens;
   73 |     |     EnumerableSet.AddressSet private _proposedRemoveWhitelistedIncentiveTokens;
   74 |     |     uint256 private _proposedAddWhitelistedIncentiveTokensEffectiveTime;
   75 |     |     uint256 private _proposedRemoveWhitelistedIncentiveTokensEffectiveTime;
   76 |     | 
   77 |     |     // Fee management
   78 |     |     // Current fee values
   79 |     |     mapping(FeeType type_ => uint256 value) private _feeValues;
   80 |     |     // Proposed fee values
   81 |     |     mapping(FeeType type_ => uint256 proposedValue) private _proposedFeeValues;
   82 |     |     // Effective times for proposed fee updates
   83 |     |     mapping(FeeType type_ => uint256 effectiveTime) private _feeEffectiveTimes;
   84 |     | 
   85 |     |     mapping(address _oracle => GasInfo info) private _oracleGasInfo;
   86 |     | 
   87 |     |     // Upkeep control
   88 |     |     bool private _upkeepPaymentsEnabled;
   89 |     |     bool private _proposedUpkeepPaymentsEnabled;
   90 |     |     uint256 private _upkeepPaymentsChangeEffectiveTime;
   91 |     | 
   92 |     |     // Superform managers (exempt from upkeep costs)
   93 |     |     EnumerableSet.AddressSet private _superformManagers;
   94 |     | 
   95 |     |     // Min staleness configuration to prevent maxStaleness from being set too low
   96 |     |     uint256 private _minStaleness;
   97 |     |     uint256 private _proposedMinStaleness;
   98 |     |     uint256 private _minStalenesEffectiveTime;
   99 |     | 
  100 |     |     // Oracle constants
  101 |     |     address private constant NATIVE_TOKEN = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
  102 |     |     address private constant USD_TOKEN = address(840);
  103 |     |     address private constant GAS_QUOTE =
  104 |     |         address(uint160(uint256(keccak256("GAS_QUOTE"))));
  105 |     |     address private constant GWEI_QUOTE =
  106 |     |         address(uint160(uint256(keccak256("GWEI_QUOTE"))));
  107 |     |     bytes32 private constant AVERAGE_PROVIDER = keccak256("AVERAGE_PROVIDER");
  108 |     | 
  109 |     |     // Timelock configuration
  110 | *   |     uint256 private constant TIMELOCK = 7 days;
  111 | *   |     uint256 private constant BPS_MAX = 10_000; // 100% in basis points
  112 |     | 
  113 |     |     // Role definitions
  114 |     |     bytes32 private constant _SUPER_GOVERNOR_ROLE = keccak256("SUPER_GOVERNOR_ROLE");
  115 |     |     bytes32 private constant _GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE");
  116 |     |     bytes32 private constant _BANK_MANAGER_ROLE = keccak256("BANK_MANAGER_ROLE");
  117 | *   |     bytes32 private constant _GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
  118 |     |     bytes32 private constant _SUPER_ASSET_FACTORY = keccak256("SUPER_ASSET_FACTORY");
  119 |     |     bytes32 private constant _GAS_MANAGER_ROLE = keccak256("GAS_MANAGER_ROLE");
  120 |     | 
  121 |     |     // Common contract keys
  122 | *   |     bytes32 public constant UP = keccak256("UP");
  123 |     |     bytes32 public constant SUP = keccak256("SUP");
  124 | *   |     bytes32 public constant TREASURY = keccak256("TREASURY");
  125 |     |     bytes32 public constant VAULT_BANK = keccak256("VAULT_BANK");
  126 | *   |     bytes32 public constant SUPER_BANK = keccak256("SUPER_BANK");
  127 |     |     bytes32 public constant SUPER_ORACLE = keccak256("SUPER_ORACLE");
  128 |     |     bytes32 public constant BANK_MANAGER = keccak256("BANK_MANAGER");
  129 |     |     bytes32 public constant ECDSAPPSORACLE = keccak256("ECDSAPPSORACLE");
  130 | *   |     bytes32 public constant SUPER_VAULT_AGGREGATOR = keccak256("SUPER_VAULT_AGGREGATOR");
  131 |     | 
  132 |     |     /*//////////////////////////////////////////////////////////////
  133 |     |                               CONSTRUCTOR
  134 |     |     //////////////////////////////////////////////////////////////*/
  135 |     |     /// @notice Initializes the SuperGovernor contract
  136 |     |     /// @param superGovernor Address of the default admin (will have SUPER_GOVERNOR_ROLE)
  137 |     |     /// @param governor Address that will have the GOVERNOR_ROLE for daily operations
  138 |     |     /// @param bankManager Address that will have the BANK_MANAGER_ROLE for daily operations
  139 |     |     /// @param treasury_ Address of the treasury
  140 |     |     /// @param prover_ Address of the prover
  141 | *   |     constructor(address superGovernor, address governor, address bankManager, address gasManager, address treasury_, address prover_) {
  142 | *   |         if (
  143 | *   |             superGovernor == address(0) || treasury_ == address(0) || governor == address(0)
  144 | *   |                 || bankManager == address(0) || prover_ == address(0) || gasManager == address(0)
  145 |     |         ) revert INVALID_ADDRESS();
  146 |     | 
  147 |     |         // Set up roles
  148 | *   |         _grantRole(DEFAULT_ADMIN_ROLE, superGovernor);
  149 | *   |         _grantRole(_SUPER_GOVERNOR_ROLE, superGovernor);
  150 | *   |         _grantRole(_GOVERNOR_ROLE, governor);
  151 | *   |         _grantRole(_BANK_MANAGER_ROLE, bankManager);
  152 | *   |         _grantRole(_GAS_MANAGER_ROLE, gasManager);
  153 |     |         // Setup GUARDIAN_ROLE without assigning any address
  154 | *   |         _setRoleAdmin(_GUARDIAN_ROLE, DEFAULT_ADMIN_ROLE);
  155 |     | 
  156 |     |         // Set role admins
  157 | *   |         _setRoleAdmin(_GOVERNOR_ROLE, DEFAULT_ADMIN_ROLE);
  158 | *   |         _setRoleAdmin(_SUPER_GOVERNOR_ROLE, DEFAULT_ADMIN_ROLE);
  159 | *   |         _setRoleAdmin(_BANK_MANAGER_ROLE, DEFAULT_ADMIN_ROLE);
  160 | *   |         _setRoleAdmin(_GAS_MANAGER_ROLE, DEFAULT_ADMIN_ROLE);
  161 |     | 
  162 |     |         // Initialize with default fees
  163 | *   |         _feeValues[FeeType.REVENUE_SHARE] = 2000; // 20% revenue share
  164 | *   |         _feeValues[FeeType.SUPER_VAULT_PERFORMANCE_FEE] = 2000; // 20% performance fee
  165 | *   |         _feeValues[FeeType.SUPER_ASSET_SWAP_FEE] = 4000; // 40% swap fee
  166 | *   |         emit FeeUpdated(FeeType.REVENUE_SHARE, _feeValues[FeeType.REVENUE_SHARE]);
  167 | *   |         emit FeeUpdated(FeeType.SUPER_VAULT_PERFORMANCE_FEE, _feeValues[FeeType.SUPER_VAULT_PERFORMANCE_FEE]);
  168 | *   |         emit FeeUpdated(FeeType.SUPER_ASSET_SWAP_FEE, _feeValues[FeeType.SUPER_ASSET_SWAP_FEE]);
  169 |     | 
  170 |     |         // Set treasury in address registry
  171 | *   |         _addressRegistry[TREASURY] = treasury_;
  172 | *   |         emit AddressSet(TREASURY, treasury_);
  173 |     | 
  174 |     |         // Initialize minimum staleness (5 minutes to prevent extremely low staleness values)
  175 | *   |         _minStaleness = 300; // 5 minutes in seconds
  176 |     | 
  177 |     |         // Initialize prover
  178 | *   |         _prover = prover_;
  179 | *   |         emit ProverSet(prover_);
  180 |     |     }
  181 |     | 
  182 |     |     /*//////////////////////////////////////////////////////////////
  183 |     |                        CONTRACT REGISTRY FUNCTIONS
  184 |     |     //////////////////////////////////////////////////////////////*/
  185 |     |     /// @inheritdoc ISuperGovernor
  186 | *   |     function setAddress(bytes32 key, address value) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  187 | *   |         if (value == address(0)) revert INVALID_ADDRESS();
  188 |     | 
  189 | *   |         _addressRegistry[key] = value;
  190 | *   |         emit AddressSet(key, value);
  191 |     |     }
  192 |     | 
  193 |     |     /*//////////////////////////////////////////////////////////////
  194 |     |                     PERIPHERY CONFIGURATIONS
  195 |     |     //////////////////////////////////////////////////////////////*/
  196 |     |     /// @inheritdoc ISuperGovernor
  197 |     |     function setProver(address prover) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  198 |     |         if (prover == address(0)) revert INVALID_ADDRESS();
  199 |     | 
  200 |     |         _prover = prover;
  201 |     |         emit ProverSet(prover);
  202 |     |     }
  203 |     | 
  204 |     |     /// @inheritdoc ISuperGovernor
  205 | *   |     function changePrimaryManager(address strategy, address newManager) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  206 |     |         // Check if takeovers are globally frozen
  207 | *   |         if (_managerTakeoversFrozen) revert MANAGER_TAKEOVERS_FROZEN();
  208 |     | 
  209 | *   |         address aggregator = _addressRegistry[SUPER_VAULT_AGGREGATOR];
  210 | *   |         if (aggregator == address(0)) revert CONTRACT_NOT_FOUND();
  211 |     | 
  212 |     |         // Call the interface method to change the manager
  213 |     |         // This function can only be called by the SuperGovernor and bypasses the timelock
  214 | *   |         ISuperVaultAggregator(aggregator).changePrimaryManager(strategy, newManager);
  215 |     |     }
  216 |     | 
  217 |     |     /// @inheritdoc ISuperGovernor
  218 |     |     function freezeManagerTakeover() external onlyRole(_SUPER_GOVERNOR_ROLE) {
  219 |     |         if (_managerTakeoversFrozen) revert MANAGER_TAKEOVERS_FROZEN();
  220 |     | 
  221 |     |         // Set frozen status to true (permanent, cannot be undone)
  222 |     |         _managerTakeoversFrozen = true;
  223 |     | 
  224 |     |         // Emit event for the frozen status
  225 |     |         emit ManagerTakeoversFrozen();
  226 |     |     }
  227 |     | 
  228 |     |     /// @inheritdoc ISuperGovernor
  229 |     |     function changeHooksRootUpdateTimelock(uint256 newTimelock) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  230 |     |         address aggregator = _addressRegistry[SUPER_VAULT_AGGREGATOR];
  231 |     |         if (aggregator == address(0)) revert CONTRACT_NOT_FOUND();
  232 |     | 
  233 |     |         // Call the SuperVaultAggregator to change the hooks root update timelock
  234 |     |         ISuperVaultAggregator(aggregator).setHooksRootUpdateTimelock(newTimelock);
  235 |     |     }
  236 |     | 
  237 |     |     /// @inheritdoc ISuperGovernor
  238 | *   |     function proposeGlobalHooksRoot(bytes32 newRoot) external onlyRole(_GOVERNOR_ROLE) {
  239 | *   |         address aggregator = _addressRegistry[SUPER_VAULT_AGGREGATOR];
  240 | *   |         if (aggregator == address(0)) revert CONTRACT_NOT_FOUND();
  241 |     | 
  242 | *   |         ISuperVaultAggregator(aggregator).proposeGlobalHooksRoot(newRoot);
  243 |     |     }
  244 |     | 
  245 |     |     /// @inheritdoc ISuperGovernor
  246 |     |     function setGlobalHooksRootVetoStatus(bool vetoed) external onlyRole(_GUARDIAN_ROLE) {
  247 |     |         address aggregator = _addressRegistry[SUPER_VAULT_AGGREGATOR];
  248 |     |         if (aggregator == address(0)) revert CONTRACT_NOT_FOUND();
  249 |     | 
  250 |     |         ISuperVaultAggregator(aggregator).setGlobalHooksRootVetoStatus(vetoed);
  251 |     |     }
  252 |     | 
  253 |     |     /// @inheritdoc ISuperGovernor
  254 |     |     function setStrategyHooksRootVetoStatus(address strategy, bool vetoed) external onlyRole(_GUARDIAN_ROLE) {
  255 |     |         if (strategy == address(0)) revert INVALID_ADDRESS();
  256 |     | 
  257 |     |         address aggregator = _addressRegistry[SUPER_VAULT_AGGREGATOR];
  258 |     |         if (aggregator == address(0)) revert CONTRACT_NOT_FOUND();
  259 |     | 
  260 |     |         ISuperVaultAggregator(aggregator).setStrategyHooksRootVetoStatus(strategy, vetoed);
  261 |     |     }
  262 |     | 
  263 |     |     /// @inheritdoc ISuperGovernor
  264 |     |     function setSuperAssetManager(address superAsset, address superAssetManager) external onlyRole(_GOVERNOR_ROLE) {
  265 |     |         if (superAsset == address(0) || superAssetManager == address(0)) revert INVALID_ADDRESS();
  266 |     |         address value = _addressRegistry[_SUPER_ASSET_FACTORY];
  267 |     |         if (value == address(0)) revert CONTRACT_NOT_FOUND();
  268 |     |         ISuperAssetFactory factory = ISuperAssetFactory(value);
  269 |     |         factory.setSuperAssetManager(superAsset, superAssetManager);
  270 |     |     }
  271 |     | 
  272 |     |     /// @inheritdoc ISuperGovernor
  273 |     |     function addICCToWhitelist(address icc) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  274 |     |         if (icc == address(0)) revert INVALID_ADDRESS();
  275 |     |         address value = _addressRegistry[_SUPER_ASSET_FACTORY];
  276 |     |         if (value == address(0)) revert CONTRACT_NOT_FOUND();
  277 |     |         ISuperAssetFactory factory = ISuperAssetFactory(value);
  278 |     |         factory.addICCToWhitelist(icc);
  279 |     |     }
  280 |     | 
  281 |     |     /// @inheritdoc ISuperGovernor
  282 |     |     function removeICCFromWhitelist(address icc) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  283 |     |         if (icc == address(0)) revert INVALID_ADDRESS();
  284 |     |         address value = _addressRegistry[_SUPER_ASSET_FACTORY];
  285 |     |         if (value == address(0)) revert CONTRACT_NOT_FOUND();
  286 |     |         ISuperAssetFactory factory = ISuperAssetFactory(value);
  287 |     |         factory.removeICCFromWhitelist(icc);
  288 |     |     }
  289 |     | 
  290 |     |     /// @inheritdoc ISuperGovernor
  291 |     |     function setOracleMaxStaleness(uint256 newMaxStaleness) external onlyRole(_GOVERNOR_ROLE) {
  292 |     |         if (newMaxStaleness < _minStaleness) revert MAX_STALENESS_TOO_LOW();
  293 |     |         address oracle = _addressRegistry[SUPER_ORACLE];
  294 |     |         if (oracle == address(0)) revert CONTRACT_NOT_FOUND();
  295 |     | 
  296 |     |         ISuperOracle(oracle).setMaxStaleness(newMaxStaleness);
  297 |     |     }
  298 |     | 
  299 |     |     /// @inheritdoc ISuperGovernor
  300 | *   |     function setOracleFeedMaxStaleness(address feed, uint256 newMaxStaleness) external onlyRole(_GOVERNOR_ROLE) {
  301 |     |         if (feed == address(0)) revert INVALID_ADDRESS();
  302 |     |         if (newMaxStaleness < _minStaleness) revert MAX_STALENESS_TOO_LOW();
  303 |     |         address oracle = _addressRegistry[SUPER_ORACLE];
  304 |     |         if (oracle == address(0)) revert CONTRACT_NOT_FOUND();
  305 |     | 
  306 | *   |         ISuperOracle(oracle).setFeedMaxStaleness(feed, newMaxStaleness);
  307 |     |     }
  308 |     | 
  309 |     |     /// @inheritdoc ISuperGovernor
  310 |     |     function setOracleFeedMaxStalenessBatch(
  311 |     |         address[] calldata feeds_,
  312 |     |         uint256[] calldata newMaxStalenessList_
  313 |     |     )
  314 |     |         external
  315 |     |         onlyRole(_GOVERNOR_ROLE)
  316 |     |     {
  317 |     |         // Validate all staleness values before proceeding
  318 |     |         for (uint256 i; i < newMaxStalenessList_.length; i++) {
  319 |     |             if (newMaxStalenessList_[i] < _minStaleness) revert MAX_STALENESS_TOO_LOW();
  320 |     |         }
  321 |     | 
  322 |     |         address oracle = _addressRegistry[SUPER_ORACLE];
  323 |     |         if (oracle == address(0)) revert CONTRACT_NOT_FOUND();
  324 |     | 
  325 |     |         ISuperOracle(oracle).setFeedMaxStalenessBatch(feeds_, newMaxStalenessList_);
  326 |     |     }
  327 |     | 
  328 |     |     /// @inheritdoc ISuperGovernor
  329 |     |     function queueOracleUpdate(
  330 |     |         address[] calldata bases_,
  331 |     |         address[] calldata quotes_,
  332 |     |         bytes32[] calldata providers_,
  333 |     |         address[] calldata feeds_
  334 |     |     )
  335 |     |         external
  336 |     |         onlyRole(_GOVERNOR_ROLE)
  337 |     |     {
  338 |     |         address oracle = _addressRegistry[SUPER_ORACLE];
  339 |     |         if (oracle == address(0)) revert CONTRACT_NOT_FOUND();
  340 |     | 
  341 |     |         ISuperOracle(oracle).queueOracleUpdate(bases_, quotes_, providers_, feeds_);
  342 |     |     }
  343 |     | 
  344 |     |     /// @inheritdoc ISuperGovernor
  345 |     |     function queueOracleProviderRemoval(bytes32[] calldata providers) external onlyRole(_GOVERNOR_ROLE) {
  346 |     |         address oracle = _addressRegistry[SUPER_ORACLE];
  347 |     |         if (oracle == address(0)) revert CONTRACT_NOT_FOUND();
  348 |     | 
  349 |     |         ISuperOracle(oracle).queueProviderRemoval(providers);
  350 |     |     }
  351 |     | 
  352 |     |     /// @inheritdoc ISuperGovernor
  353 |     |     function batchSetOracleUptimeFeed(
  354 |     |         address[] calldata dataOracles_,
  355 |     |         address[] calldata uptimeOracles_,
  356 |     |         uint256[] calldata gracePeriods_
  357 |     |     )
  358 |     |         external
  359 |     |         onlyRole(_GOVERNOR_ROLE)
  360 |     |     {
  361 |     |         address oracleL2 = _addressRegistry[SUPER_ORACLE];
  362 |     |         if (oracleL2 == address(0)) revert CONTRACT_NOT_FOUND();
  363 |     | 
  364 |     |         ISuperOracleL2(oracleL2).batchSetUptimeFeed(dataOracles_, uptimeOracles_, gracePeriods_);
  365 |     |     }
  366 |     | 
  367 |     |     /// @inheritdoc ISuperGovernor
  368 |     |     function setEmergencyPrice(address token, uint256 price) external onlyRole(_GOVERNOR_ROLE) {
  369 |     |         address oracle = _addressRegistry[SUPER_ORACLE];
  370 |     |         if (oracle == address(0)) revert CONTRACT_NOT_FOUND();
  371 |     | 
  372 |     |         ISuperOracle(oracle).setEmergencyPrice(token, price);
  373 |     |     }
  374 |     | 
  375 |     |     /// @inheritdoc ISuperGovernor
  376 | *   |     function batchSetEmergencyPrices(
  377 |     |         address[] calldata tokens_,
  378 |     |         uint256[] calldata prices_
  379 |     |     )
  380 |     |         external
  381 |     |         onlyRole(_GOVERNOR_ROLE)
  382 |     |     {
  383 |     |         address oracle = _addressRegistry[SUPER_ORACLE];
  384 |     |         if (oracle == address(0)) revert CONTRACT_NOT_FOUND();
  385 |     | 
  386 |     |         ISuperOracle(oracle).batchSetEmergencyPrice(tokens_, prices_);
  387 |     |     }
  388 |     | 
  389 |     |     /*//////////////////////////////////////////////////////////////
  390 |     |                             HOOK MANAGEMENT
  391 |     |     //////////////////////////////////////////////////////////////*/
  392 |     |     /// @inheritdoc ISuperGovernor
  393 | *   |     function registerHook(address hook, bool isFulfillRequestsHook) external onlyRole(_GOVERNOR_ROLE) {
  394 | *   |         if (hook == address(0)) revert INVALID_ADDRESS();
  395 |     | 
  396 | *   |         if (isFulfillRequestsHook && _registeredFulfillRequestsHooks.add(hook)) {
  397 | *   |             emit FulfillRequestsHookRegistered(hook);
  398 |     |         }
  399 | *   |         if (_registeredHooks.add(hook)) {
  400 | *   |             emit HookApproved(hook);
  401 |     |         }
  402 |     |     }
  403 |     | 
  404 |     |     /// @inheritdoc ISuperGovernor
  405 | *   |     function unregisterHook(address hook) external onlyRole(_GOVERNOR_ROLE) {
  406 |     |         if (_registeredFulfillRequestsHooks.remove(hook)) {
  407 |     |             emit FulfillRequestsHookUnregistered(hook);
  408 |     |         }
  409 | *   |         if (_registeredHooks.remove(hook)) {
  410 |     |             // Clear merkle root data for the unregistered hook to prevent stale data
  411 |     |             delete superBankHooksMerkleRoots[hook];
  412 |     |             delete vaultBankHooksMerkleRoots[hook];
  413 |     | 
  414 |     |             emit HookRemoved(hook);
  415 |     |         }
  416 |     |     }
  417 |     | 
  418 |     |     /*//////////////////////////////////////////////////////////////
  419 |     |                         EXECUTORS MANAGEMENT
  420 |     |     //////////////////////////////////////////////////////////////*/
  421 |     |     /// @inheritdoc ISuperGovernor
  422 |     |     function addExecutor(address executor) external onlyRole(_GOVERNOR_ROLE) {
  423 |     |         if (executor == address(0)) revert INVALID_ADDRESS();
  424 |     |         if (!_executors.add(executor)) revert EXECUTOR_ALREADY_REGISTERED();
  425 |     | 
  426 |     |         emit ExecutorAdded(executor);
  427 |     |     }
  428 |     | 
  429 |     |     /// @inheritdoc ISuperGovernor
  430 |     |     function removeExecutor(address executor) external onlyRole(_GOVERNOR_ROLE) {
  431 |     |         if (!_executors.remove(executor)) revert EXECUTOR_NOT_REGISTERED();
  432 |     | 
  433 |     |         emit ExecutorRemoved(executor);
  434 |     |     }
  435 |     | 
  436 |     |     /*//////////////////////////////////////////////////////////////
  437 |     |                           RELAYER MANAGEMENT
  438 |     |     //////////////////////////////////////////////////////////////*/
  439 |     |     /// @inheritdoc ISuperGovernor
  440 |     |     function addRelayer(address relayer) external onlyRole(_GOVERNOR_ROLE) {
  441 |     |         if (relayer == address(0)) revert INVALID_ADDRESS();
  442 |     |         if (!_relayers.add(relayer)) revert RELAYER_ALREADY_REGISTERED();
  443 |     | 
  444 |     |         emit RelayerAdded(relayer);
  445 |     |     }
  446 |     | 
  447 |     |     /// @inheritdoc ISuperGovernor
  448 |     |     function removeRelayer(address relayer) external onlyRole(_GOVERNOR_ROLE) {
  449 |     |         if (!_relayers.remove(relayer)) revert RELAYER_NOT_REGISTERED();
  450 |     | 
  451 |     |         emit RelayerRemoved(relayer);
  452 |     |     }
  453 |     | 
  454 |     |     /*//////////////////////////////////////////////////////////////
  455 |     |                         VALIDATOR MANAGEMENT
  456 |     |     //////////////////////////////////////////////////////////////*/
  457 |     |     /// @inheritdoc ISuperGovernor
  458 |     |     function addValidator(address validator) external onlyRole(_GOVERNOR_ROLE) {
  459 |     |         if (validator == address(0)) revert INVALID_ADDRESS();
  460 |     |         if (!_validators.add(validator)) revert VALIDATOR_ALREADY_REGISTERED();
  461 |     | 
  462 |     |         emit ValidatorAdded(validator);
  463 |     |     }
  464 |     | 
  465 |     |     /// @inheritdoc ISuperGovernor
  466 |     |     function removeValidator(address validator) external onlyRole(_GOVERNOR_ROLE) {
  467 |     |         if (!_validators.remove(validator)) revert VALIDATOR_NOT_REGISTERED();
  468 |     | 
  469 |     |         emit ValidatorRemoved(validator);
  470 |     |     }
  471 |     | 
  472 |     |     /*//////////////////////////////////////////////////////////////
  473 |     |                          PPS ORACLE MANAGEMENT
  474 |     |     //////////////////////////////////////////////////////////////*/
  475 |     |     /// @inheritdoc ISuperGovernor
  476 | *   |     function setActivePPSOracle(address oracle) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  477 | *   |         if (oracle == address(0)) revert INVALID_ADDRESS();
  478 |     | 
  479 |     |         // If this is the first oracle or replacing a zero oracle, set it immediately
  480 | *   |         if (_activePPSOracle == address(0)) {
  481 | *   |             _activePPSOracle = oracle;
  482 | *   |             emit ActivePPSOracleSet(oracle);
  483 |     |         } else {
  484 |     |             // Otherwise require the timelock process
  485 |     |             revert MUST_USE_TIMELOCK_FOR_CHANGE();
  486 |     |         }
  487 |     |     }
  488 |     | 
  489 |     |     /// @inheritdoc ISuperGovernor
  490 | *   |     function proposeActivePPSOracle(address oracle) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  491 |     |         if (oracle == address(0)) revert INVALID_ADDRESS();
  492 |     | 
  493 |     |         _proposedActivePPSOracle = oracle;
  494 |     |         _activePPSOracleEffectiveTime = block.timestamp + TIMELOCK;
  495 |     | 
  496 | *   |         emit ActivePPSOracleProposed(oracle, _activePPSOracleEffectiveTime);
  497 |     |     }
  498 |     | 
  499 |     |     /// @inheritdoc ISuperGovernor
  500 |     |     function executeActivePPSOracleChange() external {
  501 |     |         if (_proposedActivePPSOracle == address(0)) revert NO_PROPOSED_PPS_ORACLE();
  502 |     | 
  503 |     |         if (block.timestamp < _activePPSOracleEffectiveTime) {
  504 |     |             revert TIMELOCK_NOT_EXPIRED();
  505 |     |         }
  506 |     | 
  507 |     |         address oldOracle = _activePPSOracle;
  508 |     |         _activePPSOracle = _proposedActivePPSOracle;
  509 |     | 
  510 |     |         // Reset proposal data
  511 |     |         _proposedActivePPSOracle = address(0);
  512 |     |         _activePPSOracleEffectiveTime = 0;
  513 |     | 
  514 |     |         emit ActivePPSOracleChanged(oldOracle, _activePPSOracle);
  515 |     |     }
  516 |     | 
  517 |     |     /// @inheritdoc ISuperGovernor
  518 |     |     function setPPSOracleQuorum(uint256 quorum) external onlyRole(_GOVERNOR_ROLE) {
  519 |     |         if (quorum == 0) revert INVALID_QUORUM();
  520 |     | 
  521 |     |         _activePPSOracleQuorum = quorum;
  522 |     |         emit PPSOracleQuorumUpdated(quorum);
  523 |     |     }
  524 |     | 
  525 |     |     /*//////////////////////////////////////////////////////////////
  526 |     |                       REVENUE SHARE MANAGEMENT
  527 |     |     //////////////////////////////////////////////////////////////*/
  528 |     |     /// @inheritdoc ISuperGovernor
  529 | *   |     function proposeFee(FeeType feeType, uint256 value) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  530 | *   |         if (value > BPS_MAX) revert INVALID_FEE_VALUE();
  531 |     | 
  532 | *   |         _proposedFeeValues[feeType] = value;
  533 | *   |         _feeEffectiveTimes[feeType] = block.timestamp + TIMELOCK;
  534 |     | 
  535 | *   |         emit FeeProposed(feeType, value, _feeEffectiveTimes[feeType]);
  536 |     |     }
  537 |     | 
  538 |     |     /// @inheritdoc ISuperGovernor
  539 | *   |     function executeFeeUpdate(FeeType feeType) external {
  540 | *   |         uint256 effectiveTime = _feeEffectiveTimes[feeType];
  541 | *   |         if (effectiveTime == 0) revert NO_PROPOSED_FEE(feeType);
  542 | *   |         if (block.timestamp < effectiveTime) {
  543 | *   |             revert TIMELOCK_NOT_EXPIRED();
  544 |     |         }
  545 |     | 
  546 |     |         // Update the fee value
  547 | *   |         _feeValues[feeType] = _proposedFeeValues[feeType];
  548 |     | 
  549 |     |         // Reset proposal data
  550 | *   |         delete _proposedFeeValues[feeType];
  551 | *   |         delete _feeEffectiveTimes[feeType];
  552 |     | 
  553 | *   |         emit FeeUpdated(feeType, _feeValues[feeType]);
  554 |     |     }
  555 |     | 
  556 |     |     /// @inheritdoc ISuperGovernor
  557 | *   |     function executeUpkeepClaim(uint256 amount) external onlyRole(_GOVERNOR_ROLE) {
  558 | *   |         address aggregator = _addressRegistry[SUPER_VAULT_AGGREGATOR];
  559 | *   |         if (aggregator == address(0)) revert CONTRACT_NOT_FOUND();
  560 |     | 
  561 | *   |         ISuperVaultAggregator(aggregator).claimUpkeep(amount);
  562 |     |     }
  563 |     | 
  564 |     |     /*//////////////////////////////////////////////////////////////
  565 |     |                         UPKEEP COST MANAGEMENT
  566 |     |     //////////////////////////////////////////////////////////////*/
  567 |     |     /// @inheritdoc ISuperGovernor
  568 |     |     function setGasInfo(address oracle, uint256 baseGasBatch, uint256 gasIncreasePerEntryBatch) external onlyRole(_GAS_MANAGER_ROLE) {
  569 |     |         if (oracle == address(0)) revert INVALID_ADDRESS();
  570 |     |         if (baseGasBatch == 0 || gasIncreasePerEntryBatch == 0) revert INVALID_GAS_INFO();
  571 |     | 
  572 |     |         _oracleGasInfo[oracle] = GasInfo({baseGasBatch: baseGasBatch, gasIncreasePerEntryBatch: gasIncreasePerEntryBatch});
  573 |     |         emit GasInfoSet(oracle, baseGasBatch, gasIncreasePerEntryBatch);
  574 |     |     }
  575 |     | 
  576 |     |     /// @notice Proposes a change to the upkeep payments enabled status
  577 |     |     /// @param enabled The proposed new status for upkeep payments
  578 | *   |     function proposeUpkeepPaymentsChange(bool enabled) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  579 | *   |         _proposedUpkeepPaymentsEnabled = enabled;
  580 | *   |         _upkeepPaymentsChangeEffectiveTime = block.timestamp + TIMELOCK;
  581 |     | 
  582 | *   |         emit UpkeepPaymentsChangeProposed(enabled, _upkeepPaymentsChangeEffectiveTime);
  583 |     |     }
  584 |     | 
  585 |     |     /// @notice Executes a previously proposed change to upkeep payments status after timelock expires
  586 | *   |     function executeUpkeepPaymentsChange() external {
  587 | *   |         if (_upkeepPaymentsChangeEffectiveTime == 0) revert NO_PENDING_CHANGE();
  588 | *   |         if (block.timestamp < _upkeepPaymentsChangeEffectiveTime) revert TIMELOCK_NOT_EXPIRED();
  589 |     | 
  590 | *   |         _upkeepPaymentsEnabled = _proposedUpkeepPaymentsEnabled;
  591 | *   |         _upkeepPaymentsChangeEffectiveTime = 0;
  592 | *   |         _proposedUpkeepPaymentsEnabled = false;
  593 |     | 
  594 | *   |         emit UpkeepPaymentsChanged(_upkeepPaymentsEnabled);
  595 |     |     }
  596 |     | 
  597 |     |     /*//////////////////////////////////////////////////////////////
  598 |     |                         MIN STALENESS MANAGEMENT
  599 |     |     //////////////////////////////////////////////////////////////*/
  600 |     |     /// @inheritdoc ISuperGovernor
  601 | *   |     function proposeMinStaleness(uint256 newMinStaleness) external onlyRole(_SUPER_GOVERNOR_ROLE) {
  602 | *   |         _proposedMinStaleness = newMinStaleness;
  603 | *   |         _minStalenesEffectiveTime = block.timestamp + TIMELOCK;
  604 |     | 
  605 | *   |         emit MinStalenesProposed(newMinStaleness, _minStalenesEffectiveTime);
  606 |     |     }
  607 |     | 
  608 |     |     /// @inheritdoc ISuperGovernor
  609 | *   |     function executeMinStalenesChange() external {
  610 | *   |         uint256 minStalenesEffectiveTime = _minStalenesEffectiveTime;
  611 | *   |         if (minStalenesEffectiveTime == 0) revert NO_PROPOSED_MIN_STALENESS();
  612 | *   |         if (block.timestamp < minStalenesEffectiveTime) revert TIMELOCK_NOT_EXPIRED();
  613 |     | 
  614 | *   |         _minStaleness = _proposedMinStaleness;
  615 |     | 
  616 |     |         // Reset proposal data
  617 | *   |         _proposedMinStaleness = 0;
  618 | *   |         _minStalenesEffectiveTime = 0;
  619 |     | 
  620 | *   |         emit MinStalenesChanged(_minStaleness);
  621 |     |     }
  622 |     | 
  623 |     |     /*//////////////////////////////////////////////////////////////
  624 |     |                       SUPERFORM MANAGER MANAGEMENT
  625 |     |     //////////////////////////////////////////////////////////////*/
  626 |     |     /// @inheritdoc ISuperGovernor
  627 |     |     function addSuperformManager(address manager) external onlyRole(_GOVERNOR_ROLE) {
  628 |     |         if (manager == address(0)) revert INVALID_ADDRESS();
  629 |     |         if (!_superformManagers.add(manager)) revert MANAGER_ALREADY_REGISTERED();
  630 |     | 
  631 |     |         emit SuperformManagerAdded(manager);
  632 |     |     }
  633 |     | 
  634 |     |     /// @inheritdoc ISuperGovernor
  635 |     |     function removeSuperformManager(address manager) external onlyRole(_GOVERNOR_ROLE) {
  636 |     |         if (!_superformManagers.remove(manager)) revert MANAGER_NOT_REGISTERED();
  637 |     | 
  638 |     |         emit SuperformManagerRemoved(manager);
  639 |     |     }
  640 |     | 
  641 |     |     /*//////////////////////////////////////////////////////////////
  642 |     |                            VAULT HOOKS MGMT
  643 |     |     //////////////////////////////////////////////////////////////*/
  644 |     | 
  645 |     |     /// @inheritdoc ISuperGovernor
  646 |     |     function proposeVaultBankHookMerkleRoot(address hook, bytes32 proposedRoot) external onlyRole(_GOVERNOR_ROLE) {
  647 |     |         if (!_registeredHooks.contains(hook)) revert HOOK_NOT_APPROVED();
  648 |     |         if (proposedRoot == bytes32(0)) revert ZERO_PROPOSED_MERKLE_ROOT();
  649 |     | 
  650 |     |         uint256 effectiveTime = block.timestamp + TIMELOCK;
  651 |     |         ISuperGovernor.HookMerkleRootData storage data = vaultBankHooksMerkleRoots[hook];
  652 |     |         data.proposedRoot = proposedRoot;
  653 |     |         data.effectiveTime = effectiveTime;
  654 |     | 
  655 |     |         emit VaultBankHookMerkleRootProposed(hook, proposedRoot, effectiveTime);
  656 |     |     }
  657 |     | 
  658 |     |     /// @inheritdoc ISuperGovernor
  659 |     |     function executeVaultBankHookMerkleRootUpdate(address hook) external {
  660 |     |         if (!_registeredHooks.contains(hook)) revert HOOK_NOT_APPROVED();
  661 |     | 
  662 |     |         ISuperGovernor.HookMerkleRootData storage data = vaultBankHooksMerkleRoots[hook];
  663 |     | 
  664 |     |         // Check if there's a proposed update
  665 |     |         bytes32 proposedRoot = data.proposedRoot;
  666 |     |         if (proposedRoot == bytes32(0)) revert NO_PROPOSED_MERKLE_ROOT();
  667 |     | 
  668 |     |         // Check if the effective time has passed
  669 |     |         if (block.timestamp < data.effectiveTime) revert TIMELOCK_NOT_EXPIRED();
  670 |     | 
  671 |     |         // Update the Merkle root
  672 |     |         data.currentRoot = proposedRoot;
  673 |     | 
  674 |     |         // Reset the proposal
  675 |     |         data.proposedRoot = bytes32(0);
  676 |     |         data.effectiveTime = 0;
  677 |     | 
  678 |     |         emit VaultBankHookMerkleRootUpdated(hook, proposedRoot);
  679 |     |     }
  680 |     | 
  681 |     |     /*//////////////////////////////////////////////////////////////
  682 |     |                            SUPERBANK HOOKS MGMT
  683 |     |     //////////////////////////////////////////////////////////////*/
  684 |     |     /// @inheritdoc ISuperGovernor
  685 |     |     function proposeSuperBankHookMerkleRoot(address hook, bytes32 proposedRoot) external onlyRole(_GOVERNOR_ROLE) {
  686 |     |         if (!_registeredHooks.contains(hook)) revert HOOK_NOT_APPROVED();
  687 |     |         if (proposedRoot == bytes32(0)) revert ZERO_PROPOSED_MERKLE_ROOT();
  688 |     | 
  689 |     |         uint256 effectiveTime = block.timestamp + TIMELOCK;
  690 |     |         ISuperGovernor.HookMerkleRootData storage data = superBankHooksMerkleRoots[hook];
  691 |     |         data.proposedRoot = proposedRoot;
  692 |     |         data.effectiveTime = effectiveTime;
  693 |     | 
  694 |     |         emit SuperBankHookMerkleRootProposed(hook, proposedRoot, effectiveTime);
  695 |     |     }
  696 |     | 
  697 |     |     /// @inheritdoc ISuperGovernor
  698 |     |     function executeSuperBankHookMerkleRootUpdate(address hook) external {
  699 |     |         if (!_registeredHooks.contains(hook)) revert HOOK_NOT_APPROVED();
  700 |     | 
  701 |     |         ISuperGovernor.HookMerkleRootData storage data = superBankHooksMerkleRoots[hook];
  702 |     | 
  703 |     |         // Check if there's a proposed update
  704 |     |         bytes32 proposedRoot = data.proposedRoot;
  705 |     |         if (proposedRoot == bytes32(0)) revert NO_PROPOSED_MERKLE_ROOT();
  706 |     | 
  707 |     |         // Check if the effective time has passed
  708 |     |         if (block.timestamp < data.effectiveTime) revert TIMELOCK_NOT_EXPIRED();
  709 |     | 
  710 |     |         // Update the Merkle root
  711 |     |         data.currentRoot = proposedRoot;
  712 |     | 
  713 |     |         // Reset the proposal
  714 |     |         data.proposedRoot = bytes32(0);
  715 |     |         data.effectiveTime = 0;
  716 |     | 
  717 |     |         emit SuperBankHookMerkleRootUpdated(hook, proposedRoot);
  718 |     |     }
  719 |     | 
  720 |     |     /*//////////////////////////////////////////////////////////////
  721 |     |                         VAULT BANK MANAGEMENT
  722 |     |     //////////////////////////////////////////////////////////////*/
  723 |     |     /// @inheritdoc ISuperGovernor
  724 |     |     function addVaultBank(uint64 chainId, address vaultBank) external onlyRole(_GOVERNOR_ROLE) {
  725 |     |         if (chainId == 0) revert INVALID_CHAIN_ID();
  726 |     |         if (vaultBank == address(0)) revert INVALID_ADDRESS();
  727 |     | 
  728 |     |         if (_vaultBanksByChainId[chainId] != address(0)) {
  729 |     |             _vaultBanks.remove(_vaultBanksByChainId[chainId]);
  730 |     |         }
  731 |     | 
  732 |     |         _vaultBanks.add(vaultBank);
  733 |     |         _vaultBanksByChainId[chainId] = vaultBank;
  734 |     | 
  735 |     |         emit VaultBankAddressAdded(chainId, vaultBank);
  736 |     |     }
  737 |     | 
  738 |     |     /// @inheritdoc ISuperGovernor
  739 |     |     function getVaultBank(uint64 chainId) external view returns (address) {
  740 |     |         return _vaultBanksByChainId[chainId];
  741 |     |     }
  742 |     | 
  743 |     |     /*//////////////////////////////////////////////////////////////
  744 |     |                       INCENTIVE TOKEN MANAGEMENT
  745 |     |     //////////////////////////////////////////////////////////////*/
  746 |     |     /// @inheritdoc ISuperGovernor
  747 | *   |     function proposeAddIncentiveTokens(address[] memory tokens) external onlyRole(_GOVERNOR_ROLE) {
  748 | *   |         for (uint256 i; i < tokens.length; i++) {
  749 | *   |             if (tokens[i] == address(0)) revert INVALID_ADDRESS();
  750 | *   |             _proposedWhitelistedIncentiveTokens.add(tokens[i]);
  751 |     |         }
  752 |     | 
  753 | *   |         _proposedAddWhitelistedIncentiveTokensEffectiveTime = block.timestamp + TIMELOCK;
  754 |     | 
  755 | *   |         emit WhitelistedIncentiveTokensProposed(
  756 | *   |             _proposedWhitelistedIncentiveTokens.values(), _proposedAddWhitelistedIncentiveTokensEffectiveTime
  757 |     |         );
  758 |     |     }
  759 |     | 
  760 |     |     /// @inheritdoc ISuperGovernor
  761 | *   |     function executeAddIncentiveTokens() external {
  762 | *   |         if (
  763 | *   |             _proposedAddWhitelistedIncentiveTokensEffectiveTime == 0
  764 | *   |                 || block.timestamp < _proposedAddWhitelistedIncentiveTokensEffectiveTime
  765 | *   |         ) revert TIMELOCK_NOT_EXPIRED();
  766 |     | 
  767 |     |         // Get all proposed tokens before modifying the set
  768 | *   |         address[] memory tokensToAdd = _proposedWhitelistedIncentiveTokens.values();
  769 | *   |         uint256 len = tokensToAdd.length;
  770 |     |         address token;
  771 | *   |         for (uint256 i; i < len; i++) {
  772 | *   |             token = tokensToAdd[i];
  773 | *   |             _isWhitelistedIncentiveToken[token] = true;
  774 |     |             // Remove from proposed whitelisted tokens
  775 | *   |             _proposedWhitelistedIncentiveTokens.remove(token);
  776 |     |         }
  777 |     | 
  778 |     |         // Emit event once with all tokens
  779 | *   |         emit WhitelistedIncentiveTokensAdded(tokensToAdd);
  780 |     | 
  781 |     |         // Reset proposal timestamp
  782 | *   |         _proposedAddWhitelistedIncentiveTokensEffectiveTime = 0;
  783 |     |     }
  784 |     | 
  785 |     |     /// @inheritdoc ISuperGovernor
  786 |     |     function proposeRemoveIncentiveTokens(address[] memory tokens) external onlyRole(_GOVERNOR_ROLE) {
  787 |     |         for (uint256 i; i < tokens.length; i++) {
  788 |     |             if (tokens[i] == address(0)) revert INVALID_ADDRESS();
  789 |     |             if (!_isWhitelistedIncentiveToken[tokens[i]]) revert NOT_WHITELISTED_INCENTIVE_TOKEN();
  790 |     | 
  791 |     |             _proposedRemoveWhitelistedIncentiveTokens.add(tokens[i]);
  792 |     |         }
  793 |     | 
  794 |     |         _proposedRemoveWhitelistedIncentiveTokensEffectiveTime = block.timestamp + TIMELOCK;
  795 |     | 
  796 |     |         emit WhitelistedIncentiveTokensProposed(
  797 |     |             _proposedRemoveWhitelistedIncentiveTokens.values(), _proposedRemoveWhitelistedIncentiveTokensEffectiveTime
  798 |     |         );
  799 |     |     }
  800 |     | 
  801 |     |     /// @inheritdoc ISuperGovernor
  802 | *   |     function executeRemoveIncentiveTokens() external {
  803 | *   |         if (
  804 | *   |             _proposedRemoveWhitelistedIncentiveTokensEffectiveTime == 0
  805 |     |                 || block.timestamp < _proposedRemoveWhitelistedIncentiveTokensEffectiveTime
  806 | *   |         ) revert TIMELOCK_NOT_EXPIRED();
  807 |     | 
  808 |     |         // Get all proposed tokens before modifying the set
  809 |     |         address[] memory tokensToRemove = _proposedRemoveWhitelistedIncentiveTokens.values();
  810 |     |         uint256 len = tokensToRemove.length;
  811 |     |         address token;
  812 |     |         for (uint256 i; i < len; i++) {
  813 |     |             token = tokensToRemove[i];
  814 |     |             if (_isWhitelistedIncentiveToken[token]) {
  815 |     |                 _isWhitelistedIncentiveToken[token] = false;
  816 |     |             }
  817 |     |             // Remove from proposed whitelisted tokens to be removed
  818 |     |             _proposedRemoveWhitelistedIncentiveTokens.remove(token);
  819 |     |         }
  820 |     | 
  821 |     |         // Emit event once with all tokens
  822 |     |         emit WhitelistedIncentiveTokensRemoved(tokensToRemove);
  823 |     | 
  824 |     |         // Reset proposal timestamp
  825 |     |         _proposedRemoveWhitelistedIncentiveTokensEffectiveTime = 0;
  826 |     |     }
  827 |     | 
  828 |     |     /*//////////////////////////////////////////////////////////////
  829 |     |                          EXTERNAL VIEW FUNCTIONS
  830 |     |     //////////////////////////////////////////////////////////////*/
  831 |     |     /// @inheritdoc ISuperGovernor
  832 |     |     function SUPER_GOVERNOR_ROLE() external pure returns (bytes32) {
  833 |     |         return _SUPER_GOVERNOR_ROLE;
  834 |     |     }
  835 |     | 
  836 |     |     /// @inheritdoc ISuperGovernor
  837 |     |     function GOVERNOR_ROLE() external pure returns (bytes32) {
  838 |     |         return _GOVERNOR_ROLE;
  839 |     |     }
  840 |     | 
  841 |     |     /// @inheritdoc ISuperGovernor
  842 |     |     function BANK_MANAGER_ROLE() external pure returns (bytes32) {
  843 |     |         return _BANK_MANAGER_ROLE;
  844 |     |     }
  845 |     | 
  846 |     |     /// @inheritdoc ISuperGovernor
  847 |     |     function GAS_MANAGER_ROLE() external pure returns (bytes32) {
  848 |     |         return _GAS_MANAGER_ROLE;
  849 |     |     }
  850 |     | 
  851 |     |     /// @inheritdoc ISuperGovernor
  852 |     |     function GUARDIAN_ROLE() external pure returns (bytes32) {
  853 |     |         return _GUARDIAN_ROLE;
  854 |     |     }
  855 |     | 
  856 |     |     /// @inheritdoc ISuperGovernor
  857 |     |     function SUPER_ASSET_FACTORY() external pure returns (bytes32) {
  858 |     |         return _SUPER_ASSET_FACTORY;
  859 |     |     }
  860 |     | 
  861 |     |     /// @inheritdoc ISuperGovernor
  862 | *   |     function getAddress(bytes32 key) external view returns (address) {
  863 | *   |         address value = _addressRegistry[key];
  864 | *   |         if (value == address(0)) revert CONTRACT_NOT_FOUND();
  865 |     |         return value;
  866 |     |     }
  867 |     | 
  868 |     |     /// @inheritdoc ISuperGovernor
  869 |     |     function isManagerTakeoverFrozen() external view returns (bool) {
  870 |     |         return _managerTakeoversFrozen;
  871 |     |     }
  872 |     | 
  873 |     |     /// @inheritdoc ISuperGovernor
  874 | *   |     function isHookRegistered(address hook) external view returns (bool) {
  875 | *   |         return _registeredHooks.contains(hook);
  876 |     |     }
  877 |     | 
  878 |     |     /// @inheritdoc ISuperGovernor
  879 | *   |     function isFulfillRequestsHookRegistered(address hook) external view returns (bool) {
  880 | *   |         return _registeredFulfillRequestsHooks.contains(hook);
  881 |     |     }
  882 |     | 
  883 |     |     /// @inheritdoc ISuperGovernor
  884 |     |     function getRegisteredHooks() external view returns (address[] memory) {
  885 |     |         return _registeredHooks.values();
  886 |     |     }
  887 |     | 
  888 |     |     /// @inheritdoc ISuperGovernor
  889 |     |     function getRegisteredFulfillRequestsHooks() external view returns (address[] memory) {
  890 |     |         return _registeredFulfillRequestsHooks.values();
  891 |     |     }
  892 |     | 
  893 |     |     /// @inheritdoc ISuperGovernor
  894 |     |     function isValidator(address validator) external view returns (bool) {
  895 |     |         return _validators.contains(validator);
  896 |     |     }
  897 |     | 
  898 |     |     /// @inheritdoc ISuperGovernor
  899 |     |     function isGuardian(address guardian) external view returns (bool) {
  900 |     |         return hasRole(_GUARDIAN_ROLE, guardian);
  901 |     |     }
  902 |     | 
  903 |     |     /// @inheritdoc ISuperGovernor
  904 |     |     function isRelayer(address relayer) external view returns (bool) {
  905 |     |         return _relayers.contains(relayer);
  906 |     |     }
  907 |     | 
  908 |     |     /// @inheritdoc ISuperGovernor
  909 |     |     function isExecutor(address executor) external view returns (bool) {
  910 |     |         return _executors.contains(executor);
  911 |     |     }
  912 |     | 
  913 |     |     /// @inheritdoc ISuperGovernor
  914 |     |     function getValidators() external view returns (address[] memory) {
  915 |     |         return _validators.values();
  916 |     |     }
  917 |     | 
  918 |     |     /// @inheritdoc ISuperGovernor
  919 |     |     function getRelayers() external view returns (address[] memory) {
  920 |     |         return _relayers.values();
  921 |     |     }
  922 |     | 
  923 |     |     /// @inheritdoc ISuperGovernor
  924 |     |     function getExecutors() external view returns (address[] memory) {
  925 |     |         return _executors.values();
  926 |     |     }
  927 |     | 
  928 |     |     /// @inheritdoc ISuperGovernor
  929 |     |     function getProposedActivePPSOracle() external view returns (address proposedOracle, uint256 effectiveTime) {
  930 |     |         return (_proposedActivePPSOracle, _activePPSOracleEffectiveTime);
  931 |     |     }
  932 |     | 
  933 |     |     /// @inheritdoc ISuperGovernor
  934 |     |     function getPPSOracleQuorum() external view returns (uint256) {
  935 |     |         return _activePPSOracleQuorum;
  936 |     |     }
  937 |     | 
  938 |     |     /// @inheritdoc ISuperGovernor
  939 |     |     function getActivePPSOracle() external view returns (address) {
  940 |     |         if (_activePPSOracle == address(0)) revert NO_ACTIVE_PPS_ORACLE();
  941 |     |         return _activePPSOracle;
  942 |     |     }
  943 |     | 
  944 |     |     /// @inheritdoc ISuperGovernor
  945 | *   |     function isActivePPSOracle(address oracle) external view returns (bool) {
  946 | *   |         return oracle == _activePPSOracle;
  947 |     |     }
  948 |     | 
  949 |     |     /// @inheritdoc ISuperGovernor
  950 | *   |     function getFee(FeeType feeType) external view returns (uint256) {
  951 | *   |         return _feeValues[feeType];
  952 |     |     }
  953 |     | 
  954 |     |     /// @inheritdoc ISuperGovernor
  955 |     |     function getGasInfo(address oracle_) external view returns (GasInfo memory) {
  956 |     |         return _oracleGasInfo[oracle_];
  957 |     |     }
  958 |     | 
  959 |     |      /// @inheritdoc ISuperGovernor
  960 | *   |     function getUpkeepCostPerBatchUpdate(address oracle_, uint256 chargeableEntries_) external view returns (uint256) {
  961 |     |         // Calculate total gas cost
  962 | *   |         uint256 totalGas = _oracleGasInfo[oracle_].baseGasBatch + 
  963 | *   |             (_oracleGasInfo[oracle_].gasIncreasePerEntryBatch * chargeableEntries_);
  964 |     | 
  965 | *   |         return _convertGasToUp(totalGas);
  966 |     |     }
  967 |     | 
  968 |     |     /// @inheritdoc ISuperGovernor
  969 | *   |     function getMinStaleness() external view returns (uint256) {
  970 | *   |         return _minStaleness;
  971 |     |     }
  972 |     | 
  973 |     |     /// @inheritdoc ISuperGovernor
  974 |     |     function getProposedMinStaleness() external view returns (uint256 proposedMinStaleness, uint256 effectiveTime) {
  975 |     |         return (_proposedMinStaleness, _minStalenesEffectiveTime);
  976 |     |     }
  977 |     | 
  978 |     |     /// @inheritdoc ISuperGovernor
  979 |     |     function getSuperBankHookMerkleRoot(address hook) external view returns (bytes32) {
  980 |     |         if (!_registeredHooks.contains(hook)) revert HOOK_NOT_APPROVED();
  981 |     |         return superBankHooksMerkleRoots[hook].currentRoot;
  982 |     |     }
  983 |     | 
  984 |     |     /// @inheritdoc ISuperGovernor
  985 |     |     function getVaultBankHookMerkleRoot(address hook) external view returns (bytes32) {
  986 |     |         if (!_registeredHooks.contains(hook)) revert HOOK_NOT_APPROVED();
  987 |     |         return vaultBankHooksMerkleRoots[hook].currentRoot;
  988 |     |     }
  989 |     | 
  990 |     |     /// @inheritdoc ISuperGovernor
  991 |     |     function getProposedSuperBankHookMerkleRoot(address hook)
  992 |     |         external
  993 |     |         view
  994 |     |         returns (bytes32 proposedRoot, uint256 effectiveTime)
  995 |     |     {
  996 |     |         if (!_registeredHooks.contains(hook)) revert HOOK_NOT_APPROVED();
  997 |     |         ISuperGovernor.HookMerkleRootData storage data = superBankHooksMerkleRoots[hook];
  998 |     |         return (data.proposedRoot, data.effectiveTime);
  999 |     |     }
 1000 |     | 
 1001 |     |     /// @inheritdoc ISuperGovernor
 1002 |     |     function getProposedVaultBankHookMerkleRoot(address hook)
 1003 |     |         external
 1004 |     |         view
 1005 |     |         returns (bytes32 proposedRoot, uint256 effectiveTime)
 1006 |     |     {
 1007 |     |         if (!_registeredHooks.contains(hook)) revert HOOK_NOT_APPROVED();
 1008 |     |         ISuperGovernor.HookMerkleRootData storage data = vaultBankHooksMerkleRoots[hook];
 1009 |     |         return (data.proposedRoot, data.effectiveTime);
 1010 |     |     }
 1011 |     | 
 1012 |     |     /// @inheritdoc ISuperGovernor
 1013 |     |     function getProver() external view returns (address) {
 1014 |     |         return _prover;
 1015 |     |     }
 1016 |     | 
 1017 |     |     /// @inheritdoc ISuperGovernor
 1018 | *   |     function isUpkeepPaymentsEnabled() external view returns (bool enabled) {
 1019 | *   |         return _upkeepPaymentsEnabled;
 1020 |     |     }
 1021 |     | 
 1022 |     |     /// @inheritdoc ISuperGovernor
 1023 |     |     function getProposedUpkeepPaymentsStatus() external view returns (bool enabled, uint256 effectiveTime) {
 1024 |     |         return (_proposedUpkeepPaymentsEnabled, _upkeepPaymentsChangeEffectiveTime);
 1025 |     |     }
 1026 |     | 
 1027 |     |     /// @inheritdoc ISuperGovernor
 1028 | *   |     function isSuperformManager(address manager) external view returns (bool isSuperform) {
 1029 | *   |         return _superformManagers.contains(manager);
 1030 |     |     }
 1031 |     | 
 1032 |     |     /// @inheritdoc ISuperGovernor
 1033 |     |     function getAllSuperformManagers() external view returns (address[] memory managers) {
 1034 |     |         return _superformManagers.values();
 1035 |     |     }
 1036 |     | 
 1037 |     |     /// @inheritdoc ISuperGovernor
 1038 |     |     function getManagersPaginated(
 1039 |     |         uint256 cursor,
 1040 |     |         uint256 limit
 1041 |     |     )
 1042 |     |         external
 1043 |     |         view
 1044 |     |         returns (address[] memory chunkOfManagers, uint256 next)
 1045 |     |     {
 1046 |     |         uint256 len = _superformManagers.length();
 1047 |     | 
 1048 |     |         // clamp limit so we don’t read past end
 1049 |     |         uint256 realLimit = limit;
 1050 |     |         // If cursor is beyond the end, return empty array
 1051 |     |         if (cursor >= len) {
 1052 |     |             return (new address[](0), 0);
 1053 |     |         }
 1054 |     | 
 1055 |     |         uint256 remaining = len - cursor;
 1056 |     |         if (realLimit > remaining) realLimit = remaining;
 1057 |     | 
 1058 |     |         chunkOfManagers = new address[](realLimit);
 1059 |     |         for (uint256 i; i < realLimit; ++i) {
 1060 |     |             chunkOfManagers[i] = _superformManagers.at(cursor + i);
 1061 |     |         }
 1062 |     | 
 1063 |     |         next = (cursor + realLimit < len) ? cursor + realLimit : 0;
 1064 |     |     }
 1065 |     | 
 1066 |     |     /// @inheritdoc ISuperGovernor
 1067 |     |     function getSuperformManagersCount() external view returns (uint256) {
 1068 |     |         return _superformManagers.length();
 1069 |     |     }
 1070 |     | 
 1071 |     |     /// @inheritdoc ISuperGovernor
 1072 |     |     function isWhitelistedIncentiveToken(address token) external view returns (bool) {
 1073 |     |         return _isWhitelistedIncentiveToken[token];
 1074 |     |     }
 1075 |     | 
 1076 |     |     /// @inheritdoc ISuperGovernor
 1077 |     |     function registerProtectedKeeper(address keeper) external onlyRole(_GOVERNOR_ROLE) {
 1078 |     |         if (keeper == address(0)) revert INVALID_ADDRESS();
 1079 |     |         if (_protectedKeepers.contains(keeper)) revert KEEPER_ALREADY_REGISTERED();
 1080 |     | 
 1081 |     |         _protectedKeepers.add(keeper);
 1082 |     |         emit ProtectedKeeperRegistered(keeper);
 1083 |     |     }
 1084 |     | 
 1085 |     |     /// @inheritdoc ISuperGovernor
 1086 |     |     function unregisterProtectedKeeper(address keeper) external onlyRole(_GOVERNOR_ROLE) {
 1087 |     |         if (!_protectedKeepers.contains(keeper)) revert KEEPER_NOT_REGISTERED();
 1088 |     | 
 1089 |     |         _protectedKeepers.remove(keeper);
 1090 |     |         emit ProtectedKeeperUnregistered(keeper);
 1091 |     |     }
 1092 |     | 
 1093 |     |     /// @inheritdoc ISuperGovernor
 1094 | *   |     function isProtectedKeeper(address keeper) external view returns (bool) {
 1095 | *   |         return _protectedKeepers.contains(keeper);
 1096 |     |     }
 1097 |     | 
 1098 |     |     /// @inheritdoc ISuperGovernor
 1099 |     |     function getProtectedKeepers() external view returns (address[] memory) {
 1100 |     |         return _protectedKeepers.values();
 1101 |     |     }
 1102 |     | 
 1103 |     |     /// @inheritdoc ISuperGovernor
 1104 |     |     function getProtectedKeepersCount() external view returns (uint256) {
 1105 |     |         return _protectedKeepers.length();
 1106 |     |     }
 1107 |     | 
 1108 |     |     /*//////////////////////////////////////////////////////////////
 1109 |     |                            INTERNAL FUNCTIONS
 1110 |     |     //////////////////////////////////////////////////////////////*/
 1111 | *   |     function _convertGasToUp(uint256 gasAmount) internal view returns (uint256) {
 1112 | *   |         address oracle = _addressRegistry[SUPER_ORACLE];
 1113 | *   |         if (oracle == address(0)) revert SUPER_ORACLE_NOT_FOUND();
 1114 |     |         address upToken = _addressRegistry[UP];
 1115 |     |         if (upToken == address(0)) revert UP_NOT_FOUND();
 1116 |     | 
 1117 |     |         // Step 1: convert gas to ETH
 1118 |     |         (uint256 ethAmount,,,) = ISuperOracle(oracle).getQuoteFromProvider(
 1119 |     |             gasAmount,
 1120 |     |             GAS_QUOTE,
 1121 |     |             GWEI_QUOTE,
 1122 |     |             AVERAGE_PROVIDER
 1123 |     |         );
 1124 |     | 
 1125 |     |         // Step 2: convert ETH to USD
 1126 |     |         (uint256 ethToUsd,,,) = ISuperOracle(oracle).getQuoteFromProvider(
 1127 |     |             ethAmount,
 1128 |     |             NATIVE_TOKEN,
 1129 |     |             USD_TOKEN,
 1130 |     |             AVERAGE_PROVIDER
 1131 |     |         );
 1132 |     | 
 1133 |     |         // Step 3: convert USD to UP (how much USD per UP token)
 1134 |     |         (uint256 upPerUsd,,,) = ISuperOracle(oracle).getQuoteFromProvider(
 1135 |     |             1e18, // 1 UP token (18 decimals)
 1136 |     |             upToken,
 1137 |     |             USD_TOKEN,
 1138 |     |             AVERAGE_PROVIDER
 1139 |     |         );
 1140 |     | 
 1141 |     |         // Calculate required UP tokens
 1142 |     |         // usdAmount / upPerUsd = required UP tokens
 1143 |     |         uint256 requiredUpTokens = Math.mulDiv(ethToUsd, 1e18, upPerUsd, Math.Rounding.Ceil);
 1144 |     |         return requiredUpTokens;
 1145 |     |     }
 1146 |     | }
 1147 |     | 

/opt/scfuzzbench/work/target/src/SuperVault/SuperVault.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | // External
   5 |     | import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
   6 |     | import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
   7 |     | import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol";
   8 |     | 
   9 |     | // OpenZeppelin Upgradeable
  10 |     | import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
  11 |     | import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
  12 |     | import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
  13 |     | import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
  14 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
  15 |     | import { IERC165 } from "@openzeppelin/contracts/interfaces/IERC165.sol";
  16 |     | import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
  17 |     | import { IERC20Metadata } from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";
  18 |     | 
  19 |     | // Interfaces
  20 |     | import { ISuperVault } from "../interfaces/SuperVault/ISuperVault.sol";
  21 |     | import { ISuperVaultStrategy } from "../interfaces/SuperVault/ISuperVaultStrategy.sol";
  22 |     | import { ISuperGovernor } from "../interfaces/ISuperGovernor.sol";
  23 |     | import { ISuperVaultAggregator } from "../interfaces/SuperVault/ISuperVaultAggregator.sol";
  24 |     | import { IERC7540Operator, IERC7540Redeem, IERC7741 } from "../vendor/standards/ERC7540/IERC7540Vault.sol";
  25 |     | import { IERC7575 } from "../vendor/standards/ERC7575/IERC7575.sol";
  26 |     | import { ISuperVaultEscrow } from "../interfaces/SuperVault/ISuperVaultEscrow.sol";
  27 |     | 
  28 |     | // Libraries
  29 |     | import { AssetMetadataLib } from "../libraries/AssetMetadataLib.sol";
  30 |     | 
  31 |     | /// @title SuperVault
  32 |     | /// @author Superform Labs
  33 |     | /// @notice SuperVault vault contract implementing ERC4626 with synchronous deposits and asynchronous redeems via
  34 |     | /// ERC7540
  35 | *   | contract SuperVault is
  36 |     |     Initializable,
  37 |     |     ERC20Upgradeable,
  38 |     |     IERC7540Redeem,
  39 |     |     IERC7741,
  40 |     |     IERC4626,
  41 |     |     ISuperVault,
  42 |     |     ReentrancyGuardUpgradeable,
  43 |     |     EIP712Upgradeable
  44 |     | {
  45 |     |     using AssetMetadataLib for address;
  46 |     |     using SafeERC20 for IERC20;
  47 |     |     using Math for uint256;
  48 |     | 
  49 |     |     /*//////////////////////////////////////////////////////////////
  50 |     |                                 CONSTANTS
  51 |     |     //////////////////////////////////////////////////////////////*/
  52 | *   |     uint256 private constant REQUEST_ID = 0;
  53 | *   |     uint256 private constant BPS_PRECISION = 10_000;
  54 |     | 
  55 |     |     // EIP712 TypeHash
  56 |     |     bytes32 public constant AUTHORIZE_OPERATOR_TYPEHASH =
  57 |     |         keccak256("AuthorizeOperator(address controller,address operator,bool approved,bytes32 nonce,uint256 deadline)");
  58 |     | 
  59 |     |     /*//////////////////////////////////////////////////////////////
  60 |     |                                 STATE
  61 |     |     //////////////////////////////////////////////////////////////*/
  62 | *   |     address public share;
  63 |     |     IERC20 private _asset;
  64 |     |     uint8 private _underlyingDecimals;
  65 |     |     ISuperVaultStrategy public strategy;
  66 |     |     address public escrow;
  67 | *   |     uint256 public PRECISION;
  68 |     | 
  69 |     |     // Core contracts
  70 | *   |     ISuperGovernor public immutable superGovernor;
  71 |     | 
  72 |     |     /// @inheritdoc IERC7540Operator
  73 |     |     mapping(address owner => mapping(address operator => bool)) public isOperator;
  74 |     | 
  75 |     |     // Authorization tracking
  76 |     |     mapping(address controller => mapping(bytes32 nonce => bool used)) private _authorizations;
  77 |     | 
  78 |     |     /*//////////////////////////////////////////////////////////////
  79 |     |                             CONSTRUCTOR
  80 |     |     //////////////////////////////////////////////////////////////*/
  81 |     | 
  82 | *   |     constructor(address superGovernor_) {
  83 | *   |         if (superGovernor_ == address(0)) revert ZERO_ADDRESS();
  84 | *   |         superGovernor = ISuperGovernor(superGovernor_);
  85 | *   |         emit SuperGovernorSet(superGovernor_);
  86 |     | 
  87 | *   |         _disableInitializers();
  88 |     |     }
  89 |     | 
  90 |     |     /*//////////////////////////////////////////////////////////////
  91 |     |                             INITIALIZATION
  92 |     |     //////////////////////////////////////////////////////////////*/
  93 |     | 
  94 |     |     /// @notice Initialize the vault with required parameters
  95 |     |     /// @param asset_ The underlying asset token address
  96 |     |     /// @param name_ The name of the vault token
  97 |     |     /// @param symbol_ The symbol of the vault token
  98 |     |     /// @param strategy_ The strategy contract address
  99 |     |     /// @param escrow_ The escrow contract address
 100 | *   |     function initialize(
 101 |     |         address asset_,
 102 |     |         string memory name_,
 103 |     |         string memory symbol_,
 104 |     |         address strategy_,
 105 |     |         address escrow_
 106 |     |     )
 107 |     |         external
 108 |     |         initializer
 109 |     |     {
 110 | *   |         if (asset_ == address(0)) revert INVALID_ASSET();
 111 | *   |         if (strategy_ == address(0)) revert INVALID_STRATEGY();
 112 | *   |         if (escrow_ == address(0)) revert INVALID_ESCROW();
 113 |     | 
 114 |     |         // Initialize parent contracts
 115 | *   |         __ERC20_init(name_, symbol_);
 116 | *   |         __ReentrancyGuard_init();
 117 | *   |         __EIP712_init(name_, "1");
 118 |     | 
 119 |     |         // Set asset and precision
 120 | *   |         _asset = IERC20(asset_);
 121 | *   |         (bool success, uint8 assetDecimals) = asset_.tryGetAssetDecimals();
 122 | *   |         if (!success) revert INVALID_ASSET();
 123 | *   |         _underlyingDecimals = assetDecimals;
 124 | *   |         PRECISION = 10 ** _underlyingDecimals;
 125 | *   |         share = address(this);
 126 | *   |         strategy = ISuperVaultStrategy(strategy_);
 127 | *   |         escrow = escrow_;
 128 |     |     }
 129 |     | 
 130 |     |     /*//////////////////////////////////////////////////////////////
 131 |     |                             ERC20 OVERRIDES
 132 |     |     //////////////////////////////////////////////////////////////*/
 133 |     | 
 134 |     |     /*//////////////////////////////////////////////////////////////
 135 |     |                         USER EXTERNAL FUNCTIONS
 136 |     |     //////////////////////////////////////////////////////////////*/
 137 |     | 
 138 |     |     /// @inheritdoc IERC4626
 139 | *   |     function deposit(uint256 assets, address receiver) public override nonReentrant returns (uint256 shares) {
 140 | *   |         if (receiver == address(0)) revert ZERO_ADDRESS();
 141 | *   |         if (assets == 0) revert ZERO_AMOUNT();
 142 |     | 
 143 |     |         // Forward assets from msg-sender to strategy
 144 | *   |         _asset.safeTransferFrom(msg.sender, address(strategy), assets);
 145 |     | 
 146 |     |         // Single executor call: strategy skims entry fee, accounts on NET, returns net shares
 147 | *   |         shares = strategy.handleOperations4626Deposit(receiver, assets);
 148 | *   |         if (shares == 0) revert ZERO_AMOUNT();
 149 |     | 
 150 |     |         // Mint the net shares
 151 | *   |         _mint(receiver, shares);
 152 |     | 
 153 | *   |         emit Deposit(msg.sender, receiver, assets, shares);
 154 |     |     }
 155 |     | 
 156 |     |     /// @inheritdoc IERC4626
 157 | *   |     function mint(uint256 shares, address receiver) public override nonReentrant returns (uint256 assets) {
 158 | *   |         if (receiver == address(0)) revert ZERO_ADDRESS();
 159 | *   |         if (shares == 0) revert ZERO_AMOUNT();
 160 |     | 
 161 | *   |         uint256 assetsNet;
 162 | *   |         (assets, assetsNet) = strategy.quoteMintAssetsGross(shares);
 163 |     | 
 164 |     |         // Forward quoted gross assets from msg-sender to strategy
 165 | *   |         _asset.safeTransferFrom(msg.sender, address(strategy), assets);
 166 |     | 
 167 |     |         // Single executor call: strategy handles fees and accounts on NET
 168 | *   |         strategy.handleOperations4626Mint(receiver, shares, assets, assetsNet);
 169 |     | 
 170 |     |         // Mint the exact shares asked
 171 | *   |         _mint(receiver, shares);
 172 |     | 
 173 | *   |         emit Deposit(msg.sender, receiver, assets, shares);
 174 |     |     }
 175 |     | 
 176 |     |     /// @inheritdoc IERC7540Redeem
 177 |     |     /// @notice Once owner has authorized an operator, the operator can request a redeem with any controller address
 178 | *   |     function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256) {
 179 | *   |         if (shares == 0) revert ZERO_AMOUNT();
 180 | *   |         if (owner == address(0) || controller == address(0)) revert ZERO_ADDRESS();
 181 | *   |         if (owner != msg.sender && !isOperator[owner][msg.sender]) revert INVALID_OWNER_OR_OPERATOR();
 182 | *   |         if (balanceOf(owner) < shares) revert INVALID_AMOUNT();
 183 |     | 
 184 |     |         // Enforce auditor's invariant for current accounting model
 185 | *   |         if (controller != owner) revert CONTROLLER_MUST_EQUAL_OWNER();
 186 |     | 
 187 |     |         // Transfer shares to escrow for temporary locking
 188 | *   |         _approve(owner, escrow, shares);
 189 | *   |         ISuperVaultEscrow(escrow).escrowShares(owner, shares);
 190 |     | 
 191 |     |         // Forward to strategy (7540 path)
 192 | *   |         strategy.handleOperations7540(ISuperVaultStrategy.Operation.RedeemRequest, controller, address(0), shares);
 193 |     | 
 194 | *   |         emit RedeemRequest(controller, owner, REQUEST_ID, msg.sender, shares);
 195 |     |         return REQUEST_ID;
 196 |     |     }
 197 |     | 
 198 |     |     /// @inheritdoc ISuperVault
 199 | *   |     function cancelRedeem(address controller) external {
 200 | *   |         _validateController(controller);
 201 |     | 
 202 | *   |         uint256 shares = strategy.pendingRedeemRequest(controller);
 203 |     | 
 204 |     |         // Forward to strategy (7540 path)
 205 | *   |         strategy.handleOperations7540(ISuperVaultStrategy.Operation.CancelRedeem, controller, address(0), 0);
 206 |     | 
 207 |     |         // Return shares to controller
 208 | *   |         ISuperVaultEscrow(escrow).returnShares(controller, shares);
 209 |     | 
 210 | *   |         emit RedeemRequestCancelled(controller, msg.sender);
 211 |     |     }
 212 |     | 
 213 |     |     /// @inheritdoc IERC7540Operator
 214 | *   |     function setOperator(address operator, bool approved) external returns (bool success) {
 215 | *   |         if (msg.sender == operator) revert UNAUTHORIZED();
 216 | *   |         isOperator[msg.sender][operator] = approved;
 217 | *   |         emit OperatorSet(msg.sender, operator, approved);
 218 | *   |         return true;
 219 |     |     }
 220 |     | 
 221 |     |     /// @inheritdoc IERC7741
 222 |     |     function authorizeOperator(
 223 |     |         address controller,
 224 |     |         address operator,
 225 |     |         bool approved,
 226 |     |         bytes32 nonce,
 227 |     |         uint256 deadline,
 228 |     |         bytes memory signature
 229 |     |     )
 230 |     |         external
 231 |     |         returns (bool)
 232 |     |     {
 233 |     |         if (controller == operator) revert UNAUTHORIZED();
 234 |     |         if (block.timestamp > deadline) revert DEADLINE_PASSED();
 235 |     |         if (_authorizations[controller][nonce]) revert UNAUTHORIZED();
 236 |     | 
 237 |     |         _authorizations[controller][nonce] = true;
 238 |     | 
 239 |     |         bytes32 structHash =
 240 |     |             keccak256(abi.encode(AUTHORIZE_OPERATOR_TYPEHASH, controller, operator, approved, nonce, deadline));
 241 |     |         bytes32 digest = _hashTypedDataV4(structHash);
 242 |     | 
 243 |     |         if (!_isValidSignature(controller, digest, signature)) revert INVALID_SIGNATURE();
 244 |     | 
 245 |     |         isOperator[controller][operator] = approved;
 246 |     |         emit OperatorSet(controller, operator, approved);
 247 |     | 
 248 |     |         return true;
 249 |     |     }
 250 |     | 
 251 |     |     /*//////////////////////////////////////////////////////////////
 252 |     |                     USER EXTERNAL VIEW FUNCTIONS
 253 |     |     //////////////////////////////////////////////////////////////*/
 254 |     | 
 255 |     |     //--ERC7540--
 256 |     | 
 257 |     |     /// @inheritdoc IERC7540Redeem
 258 | *   |     function pendingRedeemRequest(
 259 |     |         uint256, /*requestId*/
 260 |     |         address controller
 261 |     |     )
 262 |     |         external
 263 |     |         view
 264 | *   |         returns (uint256 pendingShares)
 265 |     |     {
 266 | *   |         return strategy.pendingRedeemRequest(controller);
 267 |     |     }
 268 |     | 
 269 |     |     /// @inheritdoc IERC7540Redeem
 270 | *   |     function claimableRedeemRequest(
 271 |     |         uint256, /*requestId*/
 272 |     |         address controller
 273 |     |     )
 274 |     |         external
 275 |     |         view
 276 | *   |         returns (uint256 claimableShares)
 277 |     |     {
 278 | *   |         return maxRedeem(controller);
 279 |     |     }
 280 |     | 
 281 |     |     //--Operator Management--
 282 |     | 
 283 |     |     /// @inheritdoc IERC7741
 284 |     |     function authorizations(address controller, bytes32 nonce) external view returns (bool used) {
 285 |     |         return _authorizations[controller][nonce];
 286 |     |     }
 287 |     | 
 288 |     |     /// @inheritdoc IERC7741
 289 | *   |     function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
 290 | *   |         return _domainSeparatorV4();
 291 |     |     }
 292 |     | 
 293 |     |     /// @inheritdoc IERC7741
 294 | *   |     function invalidateNonce(bytes32 nonce) external {
 295 | *   |         if (_authorizations[msg.sender][nonce]) revert INVALID_NONCE();
 296 | *   |         _authorizations[msg.sender][nonce] = true;
 297 |     | 
 298 | *   |         emit NonceInvalidated(msg.sender, nonce);
 299 |     |     }
 300 |     | 
 301 |     |     /*//////////////////////////////////////////////////////////////
 302 |     |                             ERC4626 IMPLEMENTATION
 303 |     |     //////////////////////////////////////////////////////////////*/
 304 | *   |     function decimals() public view virtual override(ERC20Upgradeable, IERC20Metadata) returns (uint8) {
 305 | *   |         return _underlyingDecimals;
 306 |     |     }
 307 |     | 
 308 | *   |     function asset() public view virtual override returns (address) {
 309 | *   |         return address(_asset);
 310 |     |     }
 311 |     | 
 312 |     |     /// @inheritdoc IERC4626
 313 | *   |     function totalAssets() external view override returns (uint256) {
 314 | *   |         uint256 supply = totalSupply();
 315 | *   |         if (supply == 0) return 0;
 316 | *   |         uint256 currentPPS = _getStoredPPS();
 317 | *   |         return Math.mulDiv(supply, currentPPS, PRECISION, Math.Rounding.Floor);
 318 |     |     }
 319 |     | 
 320 |     |     /// @inheritdoc IERC4626
 321 | *   |     function convertToShares(uint256 assets) public view override returns (uint256) {
 322 | *   |         uint256 pps = _getStoredPPS();
 323 | *   |         if (pps == 0) return 0;
 324 | *   |         return Math.mulDiv(assets, PRECISION, pps, Math.Rounding.Floor);
 325 |     |     }
 326 |     | 
 327 |     |     /// @inheritdoc IERC4626
 328 | *   |     function convertToAssets(uint256 shares) public view override returns (uint256) {
 329 | *   |         uint256 currentPPS = _getStoredPPS();
 330 | *   |         if (currentPPS == 0) return 0;
 331 | *   |         return Math.mulDiv(shares, currentPPS, PRECISION, Math.Rounding.Floor);
 332 |     |     }
 333 |     | 
 334 |     |     /// @inheritdoc IERC4626
 335 | *   |     function maxDeposit(address) public view override returns (uint256) {
 336 | *   |         if (_isPaused()) return 0;
 337 | *   |         return type(uint256).max;
 338 |     |     }
 339 |     | 
 340 |     |     /// @inheritdoc IERC4626
 341 |     |     function maxMint(address) external view override returns (uint256) {
 342 |     |         if (_isPaused()) return 0;
 343 |     |         return type(uint256).max;
 344 |     |     }
 345 |     | 
 346 |     |     /// @inheritdoc IERC4626
 347 | *   |     function maxWithdraw(address owner) public view override returns (uint256) {
 348 | *   |         return strategy.claimableWithdraw(owner);
 349 |     |     }
 350 |     | 
 351 |     |     /// @inheritdoc IERC4626
 352 | *   |     function maxRedeem(address owner) public view override returns (uint256) {
 353 | *   |         uint256 withdrawPrice = strategy.getAverageWithdrawPrice(owner);
 354 | *   |         if (withdrawPrice == 0) return 0;
 355 | *   |         return maxWithdraw(owner).mulDiv(PRECISION, withdrawPrice, Math.Rounding.Floor);
 356 |     |     }
 357 |     | 
 358 |     |     /// @inheritdoc IERC4626
 359 | *   |     function previewDeposit(uint256 assets) public view override returns (uint256) {
 360 | *   |         uint256 pps = _getStoredPPS();
 361 | *   |         if (pps == 0) return 0;
 362 |     | 
 363 | *   |         (uint256 feeBps,) = _getManagementFeeConfig();
 364 |     | 
 365 | *   |         if (feeBps == 0) return Math.mulDiv(assets, PRECISION, pps, Math.Rounding.Floor);
 366 |     |         // fee-on-gross: fee = ceil(gross * feeBps / BPS)
 367 | *   |         uint256 fee = Math.mulDiv(assets, feeBps, BPS_PRECISION, Math.Rounding.Ceil);
 368 |     | 
 369 | *   |         uint256 assetsNet = assets - fee;
 370 | *   |         return Math.mulDiv(assetsNet, PRECISION, pps, Math.Rounding.Floor);
 371 |     |     }
 372 |     | 
 373 |     |     /// @inheritdoc IERC4626
 374 | *   |     function previewMint(uint256 shares) public view override returns (uint256) {
 375 | *   |         uint256 pps = _getStoredPPS();
 376 | *   |         if (pps == 0) return 0;
 377 |     | 
 378 | *   |         uint256 assetsNet = Math.mulDiv(shares, pps, PRECISION, Math.Rounding.Ceil);
 379 |     | 
 380 | *   |         (uint256 feeBps,) = _getManagementFeeConfig();
 381 | *   |         if (feeBps == 0) return assetsNet;
 382 | *   |         if (feeBps >= BPS_PRECISION) return 0; // impossible to mint (would require infinite gross)
 383 |     | 
 384 | *   |         return Math.mulDiv(assetsNet, BPS_PRECISION, (BPS_PRECISION - feeBps), Math.Rounding.Ceil);
 385 |     |     }
 386 |     | 
 387 |     |     /// @inheritdoc IERC4626
 388 | *   |     function previewWithdraw(uint256 /* assets*/ ) public pure override returns (uint256) {
 389 | *   |         revert NOT_IMPLEMENTED();
 390 |     |     }
 391 |     | 
 392 |     |     /// @inheritdoc IERC4626
 393 |     |     function previewRedeem(uint256 /* shares*/ ) public pure override returns (uint256) {
 394 |     |         revert NOT_IMPLEMENTED();
 395 |     |     }
 396 |     | 
 397 |     |     /// @inheritdoc IERC4626
 398 | *   |     function withdraw(
 399 |     |         uint256 assets,
 400 |     |         address receiver,
 401 |     |         address controller
 402 |     |     )
 403 |     |         public
 404 |     |         override
 405 |     |         nonReentrant
 406 | *   |         returns (uint256 shares)
 407 | *   |     {
 408 | *   |         if (receiver == address(0)) revert ZERO_ADDRESS();
 409 | *   |         _validateController(controller);
 410 |     | 
 411 | *   |         uint256 averageWithdrawPrice = strategy.getAverageWithdrawPrice(controller);
 412 | *   |         if (averageWithdrawPrice == 0) revert INVALID_WITHDRAW_PRICE();
 413 |     | 
 414 | *   |         uint256 maxWithdrawAmount = maxWithdraw(controller);
 415 | *   |         if (assets > maxWithdrawAmount) revert INVALID_AMOUNT();
 416 |     | 
 417 |     |         // Calculate shares based on assets and average withdraw price
 418 | *   |         shares = assets.mulDiv(PRECISION, averageWithdrawPrice, Math.Rounding.Floor);
 419 |     | 
 420 |     |         // Take assets from strategy (7540 path)
 421 | *   |         strategy.handleOperations7540(ISuperVaultStrategy.Operation.ClaimRedeem, controller, receiver, assets);
 422 |     | 
 423 | *   |         emit Withdraw(msg.sender, receiver, controller, assets, shares);
 424 |     |     }
 425 |     | 
 426 |     |     /// @inheritdoc IERC4626
 427 | *   |     function redeem(
 428 |     |         uint256 shares,
 429 |     |         address receiver,
 430 |     |         address controller
 431 |     |     )
 432 |     |         public
 433 |     |         override
 434 |     |         nonReentrant
 435 | *   |         returns (uint256 assets)
 436 |     |     {
 437 | *   |         if (receiver == address(0)) revert ZERO_ADDRESS();
 438 | *   |         _validateController(controller);
 439 |     | 
 440 | *   |         uint256 averageWithdrawPrice = strategy.getAverageWithdrawPrice(controller);
 441 | *   |         if (averageWithdrawPrice == 0) revert INVALID_WITHDRAW_PRICE();
 442 |     | 
 443 |     |         // Calculate assets based on shares and average withdraw price
 444 | *   |         assets = shares.mulDiv(averageWithdrawPrice, PRECISION, Math.Rounding.Floor);
 445 |     | 
 446 | *   |         uint256 maxWithdrawAmount = maxWithdraw(controller);
 447 | *   |         if (assets > maxWithdrawAmount) revert INVALID_AMOUNT();
 448 |     | 
 449 |     |         // Take assets from strategy (7540 path)
 450 | *   |         strategy.handleOperations7540(ISuperVaultStrategy.Operation.ClaimRedeem, controller, receiver, assets);
 451 |     | 
 452 | *   |         emit Withdraw(msg.sender, receiver, controller, assets, shares);
 453 |     |     }
 454 |     | 
 455 |     |     // @inheritdoc ISuperVault
 456 | *   |     function burnShares(uint256 amount) external {
 457 | *   |         if (msg.sender != address(strategy)) revert UNAUTHORIZED();
 458 | *   |         _burn(escrow, amount);
 459 |     |     }
 460 |     | 
 461 |     |     // @inheritdoc ISuperVault
 462 | *   |     function onRedeemClaimable(
 463 |     |         address user,
 464 |     |         uint256 assets,
 465 |     |         uint256 shares,
 466 |     |         uint256 averageWithdrawPrice,
 467 |     |         uint256 accumulatorShares,
 468 |     |         uint256 accumulatorCostBasis
 469 |     |     )
 470 |     |         external
 471 |     |     {
 472 | *   |         if (msg.sender != address(strategy)) revert UNAUTHORIZED();
 473 | *   |         emit RedeemClaimable(
 474 |     |             user, REQUEST_ID, assets, shares, averageWithdrawPrice, accumulatorShares, accumulatorCostBasis
 475 |     |         );
 476 |     |     }
 477 |     | 
 478 |     |     /*//////////////////////////////////////////////////////////////
 479 |     |                             ERC165 INTERFACE
 480 |     |     //////////////////////////////////////////////////////////////*/
 481 | *   |     function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
 482 | *   |         return interfaceId == type(IERC7540Redeem).interfaceId || interfaceId == type(IERC165).interfaceId
 483 |     |             || interfaceId == type(IERC7741).interfaceId || interfaceId == type(IERC4626).interfaceId
 484 |     |             || interfaceId == type(IERC7575).interfaceId || interfaceId == type(IERC7540Operator).interfaceId;
 485 |     |     }
 486 |     | 
 487 |     |     /*//////////////////////////////////////////////////////////////
 488 |     |                         INTERNAL FUNCTIONS
 489 |     |     //////////////////////////////////////////////////////////////*/
 490 |     |     /// @notice Validates that the controller is the msg.sender or has been authorized by the controller
 491 |     |     /// @param controller The controller to validate
 492 | *   |     function _validateController(address controller) internal view {
 493 | *   |         if (controller != msg.sender && !isOperator[controller][msg.sender]) revert INVALID_CONTROLLER();
 494 |     |     }
 495 |     | 
 496 |     |     /// @notice Verify an EIP712 signature using OpenZeppelin's ECDSA library
 497 |     |     /// @param signer The signer to verify
 498 |     |     /// @param digest The digest to verify
 499 |     |     /// @param signature The signature to verify
 500 |     |     function _isValidSignature(address signer, bytes32 digest, bytes memory signature) internal pure returns (bool) {
 501 |     |         address recoveredSigner = ECDSA.recover(digest, signature);
 502 |     |         return recoveredSigner == signer;
 503 |     |     }
 504 |     | 
 505 |     |     /// @notice Overrides the ERC20 _update function to update the state of the vault when a transfer occurs
 506 |     |     /// @param from The address of the sender
 507 |     |     /// @param to The address of the recipient
 508 |     |     /// @param value The amount of shares being transferred
 509 | *   |     function _update(address from, address to, uint256 value) internal override(ERC20Upgradeable) {
 510 |     |         /// @dev Move only accumulators pro-rata between actual users, not to/from infrastructure contracts
 511 | *   |         if (from != address(0) && to != address(0) && to != address(escrow) && from != address(escrow)) {
 512 | *   |             uint256 shares = value;
 513 |     |             // Zero-value transfers are legal: treat as accounting no-op.
 514 | *   |             if (shares > 0) {
 515 | *   |                 strategy.moveAccumulatorOnTransfer(from, to, shares);
 516 |     |             }
 517 |     |         }
 518 | *   |         super._update(from, to, value);
 519 |     |     }
 520 |     | 
 521 | *   |     function _getStoredPPS() internal view returns (uint256) {
 522 | *   |         return strategy.getStoredPPS();
 523 |     |     }
 524 |     | 
 525 |     |     /// @notice Checks if the vault is currently paused
 526 |     |     /// @dev This accesses the SuperVaultAggregator directly via the governor to determine pause status
 527 |     |     /// @return True if the vault is paused, false otherwise
 528 | *   |     function _isPaused() internal view returns (bool) {
 529 | *   |         address aggregatorAddress = superGovernor.getAddress(superGovernor.SUPER_VAULT_AGGREGATOR());
 530 | *   |         return ISuperVaultAggregator(aggregatorAddress).isStrategyPaused(address(strategy));
 531 |     |     }
 532 |     | 
 533 |     |     /// @dev Read management fee config (view-only for previews)
 534 | *   |     function _getManagementFeeConfig() internal view returns (uint256 feeBps, address recipient) {
 535 | *   |         ISuperVaultStrategy.FeeConfig memory cfg = strategy.getConfigInfo();
 536 | *   |         return (cfg.managementFeeBps, cfg.recipient);
 537 |     |     }
 538 |     | }
 539 |     | 

/opt/scfuzzbench/work/target/src/SuperVault/SuperVaultAggregator.sol
    1 |     | // SPDX-License-Identifier: UNLICENSED
    2 |     | pragma solidity 0.8.30;
    3 |     | 
    4 |     | // External
    5 |     | import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
    6 |     | import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
    7 |     | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
    8 |     | import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
    9 |     | import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
   10 |     | import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
   11 |     | 
   12 |     | // Superform
   13 |     | import {SuperVault} from "./SuperVault.sol";
   14 |     | import {SuperVaultStrategy} from "./SuperVaultStrategy.sol";
   15 |     | import {SuperVaultEscrow} from "./SuperVaultEscrow.sol";
   16 |     | import {ISuperGovernor} from "../interfaces/ISuperGovernor.sol";
   17 |     | import {ISuperVaultAggregator} from "../interfaces/SuperVault/ISuperVaultAggregator.sol";
   18 |     | // Libraries
   19 |     | import {AssetMetadataLib} from "../libraries/AssetMetadataLib.sol";
   20 |     | 
   21 |     | /// @title SuperVaultAggregator
   22 |     | /// @author Superform Labs
   23 |     | /// @notice Registry and PPS oracle for all SuperVaults
   24 |     | /// @dev Creates new SuperVault trios and manages PPS updates
   25 |     | contract SuperVaultAggregator is ISuperVaultAggregator {
   26 |     |     using AssetMetadataLib for address;
   27 |     |     using Clones for address;
   28 |     |     using SafeERC20 for IERC20;
   29 |     |     using Math for uint256;
   30 |     |     using EnumerableSet for EnumerableSet.AddressSet;
   31 |     | 
   32 |     |     /*//////////////////////////////////////////////////////////////
   33 |     |                                  STORAGE
   34 |     |     //////////////////////////////////////////////////////////////*/
   35 |     |     // Vault implementation contracts
   36 |     |     address public immutable VAULT_IMPLEMENTATION;
   37 |     |     address public immutable STRATEGY_IMPLEMENTATION;
   38 |     |     address public immutable ESCROW_IMPLEMENTATION;
   39 |     | 
   40 |     |     // Governance
   41 |     |     ISuperGovernor public immutable SUPER_GOVERNOR;
   42 |     | 
   43 |     |     // Claimable upkeep
   44 | *   |     uint256 public claimableUpkeep;
   45 |     | 
   46 |     |     // Strategy data storage
   47 |     |     mapping(address strategy => StrategyData) private _strategyData;
   48 |     | 
   49 |     |     // Upkeep balances
   50 |     |     mapping(address manager => uint256 upkeep) private _managerUpkeepBalance;
   51 |     | 
   52 |     |     // Stake balances
   53 |     |     mapping(address manager => uint256 stake) private _managerStakeBalance;
   54 |     | 
   55 |     |     // Registry of created vaults
   56 |     |     EnumerableSet.AddressSet private _superVaults;
   57 |     |     EnumerableSet.AddressSet private _superVaultStrategies;
   58 |     |     EnumerableSet.AddressSet private _superVaultEscrows;
   59 |     | 
   60 |     |     // Constant for PPS decimals
   61 |     |     uint256 public constant PPS_DECIMALS = 18;
   62 |     | 
   63 |     |     // Maximum number of secondary managers per strategy to prevent governance DoS on manager replacement
   64 | *   |     uint256 public constant MAX_SECONDARY_MANAGERS = 5;
   65 |     | 
   66 |     |     // Maximum number of strategies to process in `batchForwardPPS`
   67 | *   |     uint256 public constant MAX_STRATEGIES = 300;
   68 |     | 
   69 |     |     // Timelock for manager changes and Merkle root updates
   70 |     |     uint256 private constant _MANAGER_CHANGE_TIMELOCK = 7 days;
   71 | *   |     uint256 private _hooksRootUpdateTimelock = 15 minutes;
   72 |     | 
   73 |     |     // Global hooks Merkle root data
   74 |     |     bytes32 private _globalHooksRoot;
   75 |     |     bytes32 private _proposedGlobalHooksRoot;
   76 |     |     uint256 private _globalHooksRootEffectiveTime;
   77 |     |     bool private _globalHooksRootVetoed;
   78 |     | 
   79 |     |     // Nonce for vault creation tracking
   80 |     |     uint256 private _vaultCreationNonce;
   81 |     | 
   82 |     |     /*//////////////////////////////////////////////////////////////
   83 |     |                                MODIFIERS
   84 |     |     //////////////////////////////////////////////////////////////*/
   85 |     |     /// @notice Validates that msg.sender is the active PPS Oracle
   86 |     |     modifier onlyPPSOracle() {
   87 | *   |         if (!SUPER_GOVERNOR.isActivePPSOracle(msg.sender)) {
   88 |     |             revert UNAUTHORIZED_PPS_ORACLE();
   89 |     |         }
   90 |     |         _;
   91 |     |     }
   92 |     | 
   93 |     |     /// @notice Validates that a strategy exists (has been created by this aggregator)
   94 |     |     modifier validStrategy(address strategy) {
   95 | *   |         if (!_superVaultStrategies.contains(strategy))
   96 | *   |             revert UNKNOWN_STRATEGY();
   97 | *   |         _;
   98 |     |     }
   99 |     | 
  100 |     |     /*//////////////////////////////////////////////////////////////
  101 |     |                               CONSTRUCTOR
  102 |     |     //////////////////////////////////////////////////////////////*/
  103 |     |     /// @notice Initializes the SuperVaultAggregator
  104 |     |     /// @param superGovernor_ Address of the SuperGovernor contract
  105 |     |     /// @param vaultImpl_ Address of the pre-deployed SuperVault implementation
  106 |     |     /// @param strategyImpl_ Address of the pre-deployed SuperVaultStrategy implementation
  107 |     |     /// @param escrowImpl_ Address of the pre-deployed SuperVaultEscrow implementation
  108 |     |     constructor(
  109 |     |         address superGovernor_,
  110 |     |         address vaultImpl_,
  111 |     |         address strategyImpl_,
  112 |     |         address escrowImpl_
  113 |     |     ) {
  114 | *   |         if (superGovernor_ == address(0)) revert ZERO_ADDRESS();
  115 | *   |         if (vaultImpl_ == address(0)) revert ZERO_ADDRESS();
  116 | *   |         if (strategyImpl_ == address(0)) revert ZERO_ADDRESS();
  117 | *   |         if (escrowImpl_ == address(0)) revert ZERO_ADDRESS();
  118 |     | 
  119 | *   |         SUPER_GOVERNOR = ISuperGovernor(superGovernor_);
  120 | *   |         VAULT_IMPLEMENTATION = vaultImpl_;
  121 | *   |         STRATEGY_IMPLEMENTATION = strategyImpl_;
  122 | *   |         ESCROW_IMPLEMENTATION = escrowImpl_;
  123 |     |     }
  124 |     | 
  125 |     |     /*//////////////////////////////////////////////////////////////
  126 |     |                             VAULT CREATION
  127 |     |     //////////////////////////////////////////////////////////////*/
  128 |     |     /// @inheritdoc ISuperVaultAggregator
  129 | *   |     function createVault(
  130 |     |         VaultCreationParams calldata params
  131 | *   |     ) external returns (address superVault, address strategy, address escrow) {
  132 |     |         // Input validation
  133 | *   |         if (
  134 | *   |             params.asset == address(0) ||
  135 | *   |             params.mainManager == address(0) ||
  136 | *   |             params.feeConfig.recipient == address(0)
  137 |     |         ) {
  138 | *   |             revert ZERO_ADDRESS();
  139 |     |         }
  140 |     | 
  141 |     |         // Initialize local variables struct to avoid stack too deep
  142 |     |         VaultCreationLocalVars memory vars;
  143 |     | 
  144 |     |         // Increment nonce before creating proxies
  145 | *   |         vars.currentNonce = _vaultCreationNonce++;
  146 | *   |         vars.salt = keccak256(
  147 | *   |             abi.encode(
  148 | *   |                 msg.sender,
  149 | *   |                 params.asset,
  150 | *   |                 params.name,
  151 | *   |                 params.symbol,
  152 | *   |                 vars.currentNonce
  153 |     |             )
  154 |     |         );
  155 |     | 
  156 |     |         // Create minimal proxies
  157 | *   |         superVault = VAULT_IMPLEMENTATION.cloneDeterministic(vars.salt);
  158 | *   |         escrow = ESCROW_IMPLEMENTATION.cloneDeterministic(vars.salt);
  159 | *   |         strategy = STRATEGY_IMPLEMENTATION.cloneDeterministic(vars.salt);
  160 |     | 
  161 |     |         // Initialize superVault
  162 | *   |         SuperVault(superVault).initialize(
  163 | *   |             params.asset,
  164 | *   |             params.name,
  165 | *   |             params.symbol,
  166 | *   |             strategy,
  167 | *   |             escrow
  168 |     |         );
  169 |     | 
  170 |     |         // Initialize escrow
  171 | *   |         SuperVaultEscrow(escrow).initialize(superVault, strategy);
  172 |     | 
  173 |     |         // Initialize strategy
  174 | *   |         SuperVaultStrategy(payable(strategy)).initialize(
  175 | *   |             superVault,
  176 | *   |             params.feeConfig
  177 |     |         );
  178 |     | 
  179 |     |         // Store vault trio in registry
  180 | *   |         _superVaults.add(superVault);
  181 | *   |         _superVaultStrategies.add(strategy);
  182 | *   |         _superVaultEscrows.add(escrow);
  183 |     | 
  184 |     |         // Get asset decimals
  185 | *   |         (bool success, uint8 assetDecimals) = params
  186 |     |             .asset
  187 |     |             .tryGetAssetDecimals();
  188 | *   |         if (!success) revert INVALID_ASSET();
  189 | *   |         vars.initialPPS = 10 ** assetDecimals; // 1.0 as initial PPS
  190 |     | 
  191 |     |         // Validate maxStaleness against minimum required staleness
  192 | *   |         if (params.maxStaleness < SUPER_GOVERNOR.getMinStaleness()) {
  193 | *   |             revert MAX_STALENESS_TOO_LOW();
  194 |     |         }
  195 |     | 
  196 |     |         // Initialize StrategyData individually to avoid mapping assignment issues
  197 | *   |         _strategyData[strategy].pps = vars.initialPPS;
  198 |     |         // Initialize standard deviation to 0
  199 | *   |         _strategyData[strategy].lastUpdateTimestamp = block.timestamp;
  200 | *   |         _strategyData[strategy].minUpdateInterval = params.minUpdateInterval;
  201 | *   |         _strategyData[strategy].maxStaleness = params.maxStaleness;
  202 | *   |         _strategyData[strategy].isPaused = false;
  203 | *   |         _strategyData[strategy].mainManager = params.mainManager;
  204 |     | 
  205 | *   |         uint256 secondaryLen = params.secondaryManagers.length;
  206 | *   |         for (uint256 i; i < secondaryLen; ++i) {
  207 | *   |             _strategyData[strategy].secondaryManagers.add(
  208 | *   |                 params.secondaryManagers[i]
  209 |     |             );
  210 |     |         }
  211 | *   |         if (
  212 | *   |             _strategyData[strategy].secondaryManagers.length() >=
  213 |     |             MAX_SECONDARY_MANAGERS
  214 |     |         ) {
  215 | *   |             revert TOO_MANY_SECONDARY_MANAGERS();
  216 |     |         }
  217 |     | 
  218 |     |         // Set default threshold values
  219 | *   |         _strategyData[strategy].dispersionThreshold = type(uint256).max; // Default: max (disabled)
  220 | *   |         _strategyData[strategy].deviationThreshold = type(uint256).max; // Default: max (disabled)
  221 |     | 
  222 | *   |         emit VaultDeployed(
  223 |     |             superVault,
  224 |     |             strategy,
  225 | *   |             escrow,
  226 | *   |             params.asset,
  227 | *   |             params.name,
  228 | *   |             params.symbol,
  229 | *   |             vars.currentNonce
  230 |     |         );
  231 | *   |         emit PPSUpdated(
  232 |     |             strategy,
  233 | *   |             vars.initialPPS,
  234 | *   |             0,
  235 |     |             0,
  236 |     |             0,
  237 | *   |             _strategyData[strategy].lastUpdateTimestamp
  238 |     |         );
  239 |     | 
  240 | *   |         return (superVault, strategy, escrow);
  241 |     |     }
  242 |     | 
  243 |     |     /*//////////////////////////////////////////////////////////////
  244 |     |                           PPS UPDATE FUNCTIONS
  245 |     |     //////////////////////////////////////////////////////////////*/
  246 |     |     /// @inheritdoc ISuperVaultAggregator
  247 | *   |     function forwardPPS(ForwardPPSArgs calldata args) external onlyPPSOracle {
  248 | *   |         uint256 strategiesLength = args.strategies.length;
  249 | *   |         if (strategiesLength > MAX_STRATEGIES) revert MAX_STRATEGIES_EXCEEDED();
  250 |     | 
  251 | *   |         if (strategiesLength == 0) revert ZERO_ARRAY_LENGTH();
  252 |     |         // Validate input array lengths
  253 | *   |         if (
  254 | *   |             strategiesLength != args.ppss.length ||
  255 | *   |             strategiesLength != args.ppsStdevs.length ||
  256 | *   |             strategiesLength != args.validatorSets.length ||
  257 | *   |             strategiesLength != args.timestamps.length ||
  258 | *   |             strategiesLength != args.totalValidators.length
  259 | *   |         ) revert ARRAY_LENGTH_MISMATCH();
  260 |     | 
  261 | *   |         bool paymentsEnabled = SUPER_GOVERNOR.isUpkeepPaymentsEnabled();
  262 | *   |         uint256 chargeableCount;
  263 | *   |         if (paymentsEnabled) {
  264 | *   |             for (uint256 i; i < strategiesLength; ++i) {
  265 |     |                 // Skip invalid strategies without reverting
  266 | *   |                 if (!_superVaultStrategies.contains(args.strategies[i])) {
  267 |     |                     emit UnknownStrategy(args.strategies[i]);
  268 |     |                     continue;
  269 |     |                 }
  270 |     | 
  271 |     |                 // Skip when invalid timestamp is provided
  272 | *   |                 if (args.timestamps[i] > block.timestamp) {
  273 |     |                     emit ProvidedTimestampExceedsBlockTimestamp(
  274 |     |                         args.strategies[i],
  275 |     |                         args.timestamps[i],
  276 |     |                         block.timestamp
  277 |     |                     );
  278 |     |                     continue;
  279 |     |                 }
  280 |     | 
  281 |     |                 // Skip Superform manager
  282 | *   |                 address manager = _strategyData[args.strategies[i]].mainManager;
  283 | *   |                 if (SUPER_GOVERNOR.isSuperformManager(manager)) {
  284 |     |                     emit SuperformManager(args.strategies[i], manager);
  285 |     |                     continue;
  286 |     |                 }
  287 |     | 
  288 |     |                 // Skip if updateAuthority is in the authorized callers list
  289 |     |                 // These are manager-designated keepers that should be exempt from fees
  290 |     |                 // NOTE: Protected keepers cannot be added to this list (blocked in addAuthorizedCaller)
  291 |     |                 /// @dev: cannot underflow; it's checked above already and it skips the entry if that's the case
  292 | *   |                 if (
  293 | *   |                     _strategyData[args.strategies[i]]
  294 |     |                         .authorizedCallers
  295 | *   |                         .contains(args.updateAuthority)
  296 |     |                 ) {
  297 |     |                     emit AuthorizedCaller(
  298 |     |                         args.strategies[i],
  299 |     |                         args.updateAuthority
  300 |     |                     );
  301 |     |                     continue;
  302 |     |                 }
  303 |     | 
  304 |     |                 // Count only non-stale entries as chargeable
  305 | *   |                 if (
  306 | *   |                     block.timestamp - args.timestamps[i] <=
  307 | *   |                     _strategyData[args.strategies[i]].maxStaleness
  308 |     |                 ) {
  309 | *   |                     ++chargeableCount;
  310 |     |                 }
  311 |     |             }
  312 |     |         }
  313 |     | 
  314 |     |         ///@dev Total upkeep cost is determined by the oracle based on the number of chargeable entries
  315 | *   |         uint256 totalCost = paymentsEnabled
  316 | *   |             ? SUPER_GOVERNOR.getUpkeepCostPerBatchUpdate(
  317 | *   |                 msg.sender,
  318 |     |                 chargeableCount
  319 |     |             )
  320 | *   |             : 0;
  321 |     | 
  322 |     |         // Compute per-entry charge
  323 | *   |         uint256 perEntry = 0;
  324 | *   |         if (paymentsEnabled && chargeableCount > 0) {
  325 |     |             perEntry = totalCost / chargeableCount;
  326 |     |         }
  327 |     | 
  328 |     |         // Process all valid strategies
  329 | *   |         for (uint256 i; i < strategiesLength; ++i) {
  330 |     |             // Skip invalid strategies without reverting
  331 | *   |             if (!_superVaultStrategies.contains(args.strategies[i])) continue;
  332 |     | 
  333 |     |             // Skip when invalid timestamp is provided (future timestamp)
  334 | *   |             if (args.timestamps[i] > block.timestamp) {
  335 |     |                 emit ProvidedTimestampExceedsBlockTimestamp(
  336 |     |                     args.strategies[i],
  337 |     |                     args.timestamps[i],
  338 |     |                     block.timestamp
  339 |     |                 );
  340 |     |                 continue;
  341 |     |             }
  342 |     | 
  343 | *   |             uint256 upkeepCost;
  344 | *   |             if (paymentsEnabled) {
  345 |     |                 // check exemption due to staleness of a given strategy
  346 |     |                 /// @dev cannot underflow as it's already checked above, in the previous `for` loop
  347 | *   |                 if (
  348 |     |                     block.timestamp - args.timestamps[i] >
  349 |     |                     _strategyData[args.strategies[i]].maxStaleness
  350 |     |                 ) {
  351 |     |                     upkeepCost = 0;
  352 |     |                     emit StaleUpdate(
  353 |     |                         args.strategies[i],
  354 |     |                         args.updateAuthority,
  355 |     |                         args.timestamps[i]
  356 |     |                     );
  357 |     |                 } else {
  358 |     |                     address manager = _strategyData[args.strategies[i]]
  359 |     |                         .mainManager;
  360 |     |                     if (
  361 |     |                         SUPER_GOVERNOR.isSuperformManager(manager) ||
  362 |     |                         _strategyData[args.strategies[i]]
  363 |     |                             .authorizedCallers
  364 |     |                             .contains(args.updateAuthority)
  365 |     |                     ) {
  366 |     |                         upkeepCost = 0;
  367 |     |                     } else {
  368 |     |                         // Split the total batch cost fairly across chargeable entries
  369 |     |                         upkeepCost = perEntry;
  370 |     |                     }
  371 |     |                 }
  372 |     |             }
  373 |     | 
  374 |     |             // Forward update
  375 | *   |             _forwardPPS(
  376 | *   |                 PPSUpdateData({
  377 | *   |                     strategy: args.strategies[i],
  378 | *   |                     isExempt: (!paymentsEnabled) || (upkeepCost == 0), // If payments are disabled or the update is exempt from UP payments
  379 | *   |                     pps: args.ppss[i],
  380 | *   |                     ppsStdev: args.ppsStdevs[i],
  381 | *   |                     validatorSet: args.validatorSets[i],
  382 | *   |                     totalValidators: args.totalValidators[i],
  383 | *   |                     timestamp: args.timestamps[i],
  384 | *   |                     upkeepCost: upkeepCost
  385 |     |                 })
  386 |     |             );
  387 |     |         }
  388 |     |     }
  389 |     | 
  390 |     |     /*//////////////////////////////////////////////////////////////
  391 |     |                         UPKEEP MANAGEMENT
  392 |     |     //////////////////////////////////////////////////////////////*/
  393 |     |     /// @inheritdoc ISuperVaultAggregator
  394 | *   |     function depositUpkeep(address manager, uint256 amount) external {
  395 | *   |         if (amount == 0) revert ZERO_AMOUNT();
  396 |     | 
  397 |     |         // Get the UP token address from SUPER_GOVERNOR
  398 | *   |         address upToken = SUPER_GOVERNOR.getAddress(SUPER_GOVERNOR.UP());
  399 |     | 
  400 |     |         // Transfer UP tokens from msg.sender to this contract
  401 | *   |         IERC20(upToken).safeTransferFrom(msg.sender, address(this), amount);
  402 |     | 
  403 |     |         // Update upkeep balance
  404 | *   |         _managerUpkeepBalance[manager] += amount;
  405 |     | 
  406 | *   |         emit UpkeepDeposited(manager, amount);
  407 |     |     }
  408 |     | 
  409 |     |     /// @inheritdoc ISuperVaultAggregator
  410 | *   |     function claimUpkeep(uint256 amount) external {
  411 |     |         // Only SUPER_GOVERNOR can claim upkeep
  412 | *   |         if (msg.sender != address(SUPER_GOVERNOR)) {
  413 | *   |             revert CALLER_NOT_AUTHORIZED();
  414 |     |         }
  415 |     | 
  416 | *   |         if (claimableUpkeep < amount) revert INSUFFICIENT_UPKEEP();
  417 | *   |         claimableUpkeep -= amount;
  418 |     | 
  419 |     |         // Get the UP token address from SUPER_GOVERNOR
  420 | *   |         address upToken = SUPER_GOVERNOR.getAddress(SUPER_GOVERNOR.UP());
  421 |     | 
  422 |     |         // Transfer UP tokens to `SuperBank`
  423 | *   |         address _superBank = _getSuperBank();
  424 | *   |         IERC20(upToken).safeTransfer(_superBank, amount);
  425 | *   |         emit UpkeepClaimed(_superBank, amount);
  426 |     |     }
  427 |     | 
  428 |     |     /// @inheritdoc ISuperVaultAggregator
  429 | *   |     function withdrawUpkeep(uint256 amount) external {
  430 | *   |         if (amount == 0) revert ZERO_AMOUNT();
  431 |     | 
  432 |     |         // Check sufficient balance
  433 | *   |         if (_managerUpkeepBalance[msg.sender] < amount) {
  434 | *   |             revert INSUFFICIENT_UPKEEP_BALANCE();
  435 |     |         }
  436 |     | 
  437 |     |         // Get the UP token address from SUPER_GOVERNOR
  438 | *   |         address upToken = SUPER_GOVERNOR.getAddress(SUPER_GOVERNOR.UP());
  439 |     | 
  440 |     |         // Update upkeep balance
  441 |     |         unchecked {
  442 | *   |             _managerUpkeepBalance[msg.sender] -= amount;
  443 |     |         }
  444 |     | 
  445 |     |         // Transfer UP tokens to manager
  446 | *   |         IERC20(upToken).safeTransfer(msg.sender, amount);
  447 |     | 
  448 | *   |         emit UpkeepWithdrawn(msg.sender, amount);
  449 |     |     }
  450 |     | 
  451 |     |     /*//////////////////////////////////////////////////////////////
  452 |     |                         STAKE MANAGEMENT
  453 |     |     //////////////////////////////////////////////////////////////*/
  454 |     |     /// @notice Deposits UP tokens as stake for manager economic security
  455 |     |     /// @param manager Address of the manager to deposit stake for
  456 |     |     /// @param amount Amount of UP tokens to deposit as stake
  457 | *   |     function depositStake(address manager, uint256 amount) external {
  458 | *   |         if (amount == 0) revert ZERO_ADDRESS(); // Reusing error code for consistency
  459 | *   |         if (manager == address(0)) revert ZERO_ADDRESS();
  460 |     | 
  461 |     |         // Get the UP token address from SUPER_GOVERNOR
  462 | *   |         address upToken = SUPER_GOVERNOR.getAddress(SUPER_GOVERNOR.UP());
  463 |     | 
  464 |     |         // Transfer UP tokens from msg.sender to this contract
  465 | *   |         IERC20(upToken).safeTransferFrom(msg.sender, address(this), amount);
  466 |     | 
  467 |     |         // Update stake balance
  468 | *   |         _managerStakeBalance[manager] += amount;
  469 |     | 
  470 | *   |         emit StakeDeposited(manager, amount);
  471 |     |     }
  472 |     | 
  473 |     |     /// @notice Withdraws UP tokens from stake balance
  474 |     |     /// @param amount Amount of UP tokens to withdraw from stake
  475 | *   |     function withdrawStake(uint256 amount) external {
  476 | *   |         if (amount == 0) revert ZERO_ADDRESS(); // Reusing error code for consistency
  477 |     | 
  478 |     |         // Check sufficient balance
  479 | *   |         if (_managerStakeBalance[msg.sender] < amount) {
  480 | *   |             revert INSUFFICIENT_STAKE_BALANCE();
  481 |     |         }
  482 |     | 
  483 |     |         // Get the UP token address from SUPER_GOVERNOR
  484 | *   |         address upToken = SUPER_GOVERNOR.getAddress(SUPER_GOVERNOR.UP());
  485 |     | 
  486 |     |         // Update stake balance
  487 |     |         unchecked {
  488 | *   |             _managerStakeBalance[msg.sender] -= amount;
  489 |     |         }
  490 |     | 
  491 |     |         // Transfer UP tokens to manager
  492 | *   |         IERC20(upToken).safeTransfer(msg.sender, amount);
  493 |     | 
  494 | *   |         emit StakeWithdrawn(msg.sender, amount);
  495 |     |     }
  496 |     | 
  497 |     |     /// @notice Slashes a manager's stake balance by a specified amount
  498 |     |     /// @param manager The manager whose stake will be slashed
  499 |     |     /// @param amount The amount of UP tokens to slash from the manager's stake balance
  500 | *   |     function slashStake(address manager, uint256 amount) external {
  501 |     |         // Only SUPER_GOVERNOR can slash stake
  502 | *   |         if (msg.sender != address(SUPER_GOVERNOR)) {
  503 | *   |             revert CALLER_NOT_AUTHORIZED();
  504 |     |         }
  505 |     | 
  506 |     |         // Validate inputs
  507 |     |         if (manager == address(0)) revert ZERO_ADDRESS();
  508 |     |         if (amount == 0) revert ZERO_ADDRESS(); // Reusing error code for consistency
  509 |     | 
  510 |     |         // Check if manager has sufficient stake balance to slash
  511 |     |         if (_managerStakeBalance[manager] < amount) {
  512 |     |             revert INSUFFICIENT_STAKE_BALANCE();
  513 |     |         }
  514 |     | 
  515 |     |         // Reduce manager's stake balance
  516 |     |         _managerStakeBalance[manager] -= amount;
  517 |     | 
  518 |     |         // Get the UP token address and SuperBank address
  519 |     |         address upToken = SUPER_GOVERNOR.getAddress(SUPER_GOVERNOR.UP());
  520 |     |         address superBank = _getSuperBank();
  521 |     | 
  522 |     |         // Transfer slashed amount directly to SuperBank
  523 |     |         IERC20(upToken).safeTransfer(superBank, amount);
  524 |     | 
  525 |     |         // Emit event for transparency
  526 |     |         emit StakeSlashed(manager, amount);
  527 |     |     }
  528 |     | 
  529 |     |     /*//////////////////////////////////////////////////////////////
  530 |     |                         AUTHORIZED CALLER MANAGEMENT
  531 |     |     //////////////////////////////////////////////////////////////*/
  532 |     |     /// @inheritdoc ISuperVaultAggregator
  533 | *   |     function addAuthorizedCaller(
  534 |     |         address strategy,
  535 |     |         address caller
  536 | *   |     ) external validStrategy(strategy) {
  537 |     |         // Either primary or secondary manager can add authorized callers
  538 | *   |         if (!isAnyManager(msg.sender, strategy))
  539 | *   |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  540 |     | 
  541 | *   |         if (caller == address(0)) revert ZERO_ADDRESS();
  542 |     | 
  543 |     |         // Prevent managers from adding protected keepers to circumvent fees
  544 | *   |         if (SUPER_GOVERNOR.isProtectedKeeper(caller)) {
  545 |     |             revert CANNOT_ADD_PROTECTED_KEEPER();
  546 |     |         }
  547 |     | 
  548 |     |         // Check if caller is already authorized and add if not
  549 | *   |         if (!_strategyData[strategy].authorizedCallers.add(caller)) {
  550 | *   |             revert CALLER_ALREADY_AUTHORIZED();
  551 |     |         }
  552 | *   |         emit AuthorizedCallerAdded(strategy, caller);
  553 |     |     }
  554 |     | 
  555 |     |     /// @inheritdoc ISuperVaultAggregator
  556 | *   |     function removeAuthorizedCaller(
  557 |     |         address strategy,
  558 |     |         address caller
  559 | *   |     ) external validStrategy(strategy) {
  560 |     |         // Either primary or secondary manager can remove authorized callers
  561 | *   |         if (!isAnyManager(msg.sender, strategy))
  562 | *   |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  563 |     | 
  564 |     |         // Remove the caller
  565 | *   |         if (!_strategyData[strategy].authorizedCallers.remove(caller)) {
  566 | *   |             revert CALLER_NOT_AUTHORIZED();
  567 |     |         }
  568 |     |         emit AuthorizedCallerRemoved(strategy, caller);
  569 |     |     }
  570 |     | 
  571 |     |     /*//////////////////////////////////////////////////////////////
  572 |     |                        MANAGER MANAGEMENT FUNCTIONS
  573 |     |     //////////////////////////////////////////////////////////////*/
  574 |     |     /// @inheritdoc ISuperVaultAggregator
  575 | *   |     function addSecondaryManager(
  576 |     |         address strategy,
  577 |     |         address manager
  578 | *   |     ) external validStrategy(strategy) {
  579 |     |         // Only the primary manager can add secondary managers
  580 | *   |         if (msg.sender != _strategyData[strategy].mainManager)
  581 | *   |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  582 |     | 
  583 | *   |         if (manager == address(0)) revert ZERO_ADDRESS();
  584 |     | 
  585 |     |         // Check if manager is already the primary manager
  586 | *   |         if (_strategyData[strategy].mainManager == manager)
  587 | *   |             revert MANAGER_ALREADY_EXISTS();
  588 |     | 
  589 |     |         // Enforce a cap on secondary managers to prevent governance DoS on changePrimaryManager
  590 | *   |         if (
  591 | *   |             _strategyData[strategy].secondaryManagers.length() >=
  592 |     |             MAX_SECONDARY_MANAGERS
  593 |     |         ) {
  594 |     |             revert TOO_MANY_SECONDARY_MANAGERS();
  595 |     |         }
  596 |     | 
  597 |     |         // Add as secondary manager using EnumerableSet
  598 | *   |         if (!_strategyData[strategy].secondaryManagers.add(manager))
  599 | *   |             revert MANAGER_ALREADY_EXISTS();
  600 |     | 
  601 | *   |         emit SecondaryManagerAdded(strategy, manager);
  602 |     |     }
  603 |     | 
  604 |     |     /// @inheritdoc ISuperVaultAggregator
  605 | *   |     function removeSecondaryManager(
  606 |     |         address strategy,
  607 |     |         address manager
  608 | *   |     ) external validStrategy(strategy) {
  609 |     |         // Only the primary manager can remove secondary managers
  610 | *   |         if (msg.sender != _strategyData[strategy].mainManager)
  611 | *   |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  612 |     | 
  613 |     |         // Remove the manager using EnumerableSet
  614 | *   |         if (!_strategyData[strategy].secondaryManagers.remove(manager))
  615 | *   |             revert MANAGER_NOT_FOUND();
  616 |     | 
  617 | *   |         emit SecondaryManagerRemoved(strategy, manager);
  618 |     |     }
  619 |     | 
  620 |     |     /// @inheritdoc ISuperVaultAggregator
  621 | *   |     function updatePPSVerificationThresholds(
  622 |     |         address strategy,
  623 |     |         uint256 dispersionThreshold_,
  624 |     |         uint256 deviationThreshold_,
  625 |     |         uint256 mnThreshold_
  626 | *   |     ) external validStrategy(strategy) {
  627 |     |         // Since this is a risky call, we only allow main managers as callers
  628 | *   |         if (msg.sender != _strategyData[strategy].mainManager) {
  629 | *   |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  630 |     |         }
  631 |     | 
  632 |     |         // Update the thresholds
  633 | *   |         _strategyData[strategy].dispersionThreshold = dispersionThreshold_;
  634 | *   |         _strategyData[strategy].deviationThreshold = deviationThreshold_;
  635 | *   |         _strategyData[strategy].mnThreshold = mnThreshold_;
  636 |     | 
  637 |     |         // Emit the event
  638 | *   |         emit PPSVerificationThresholdsUpdated(
  639 |     |             strategy,
  640 |     |             dispersionThreshold_,
  641 |     |             deviationThreshold_,
  642 |     |             mnThreshold_
  643 |     |         );
  644 |     |     }
  645 |     | 
  646 |     |     /// @inheritdoc ISuperVaultAggregator
  647 |     |     function changeGlobalLeavesStatus(
  648 |     |         bytes32[] memory leaves,
  649 |     |         bool[] memory statuses,
  650 |     |         address strategy
  651 |     |     ) external validStrategy(strategy) {
  652 |     |         // Only the primary manager can change global leaves status
  653 |     |         if (msg.sender != _strategyData[strategy].mainManager) {
  654 |     |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  655 |     |         }
  656 |     |         uint256 leavesLen = leaves.length;
  657 |     |         // Check array lengths match
  658 |     |         if (leavesLen != statuses.length) {
  659 |     |             revert MISMATCHED_ARRAY_LENGTHS();
  660 |     |         }
  661 |     | 
  662 |     |         // Update banned status for each leaf
  663 |     |         for (uint256 i; i < leavesLen; i++) {
  664 |     |             _strategyData[strategy].bannedLeaves[leaves[i]] = statuses[i];
  665 |     |         }
  666 |     | 
  667 |     |         // Emit event
  668 |     |         emit GlobalLeavesStatusChanged(strategy, leaves, statuses);
  669 |     |     }
  670 |     | 
  671 |     |     /// @inheritdoc ISuperVaultAggregator
  672 | *   |     function changePrimaryManager(
  673 |     |         address strategy,
  674 |     |         address newManager
  675 | *   |     ) external validStrategy(strategy) {
  676 |     |         // Only SuperGovernor can call this
  677 | *   |         if (msg.sender != address(SUPER_GOVERNOR)) {
  678 | *   |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  679 |     |         }
  680 |     | 
  681 | *   |         if (strategy == address(0)) revert ZERO_ADDRESS();
  682 |     | 
  683 | *   |         if (newManager == address(0)) revert ZERO_ADDRESS();
  684 |     | 
  685 | *   |         address oldManager = _strategyData[strategy].mainManager;
  686 |     | 
  687 |     |         // SECURITY: Clear any pending manager proposals to prevent malicious re-takeover
  688 | *   |         _strategyData[strategy].proposedManager = address(0);
  689 | *   |         _strategyData[strategy].managerChangeEffectiveTime = 0;
  690 |     | 
  691 |     |         // SECURITY: Clear any pending hooks root proposals to prevent malicious hook updates
  692 | *   |         _strategyData[strategy].proposedHooksRoot = bytes32(0);
  693 | *   |         _strategyData[strategy].hooksRootEffectiveTime = 0;
  694 |     | 
  695 |     |         // SECURITY: Clear all secondary managers as they may be controlled by malicious manager
  696 |     |         // Get all secondary managers first to emit proper events
  697 | *   |         address[] memory clearedSecondaryManagers = _strategyData[strategy]
  698 |     |             .secondaryManagers
  699 |     |             .values();
  700 |     | 
  701 |     |         // Clear the entire secondary managers set
  702 | *   |         for (uint256 i = 0; i < clearedSecondaryManagers.length; i++) {
  703 | *   |             _strategyData[strategy].secondaryManagers.remove(
  704 | *   |                 clearedSecondaryManagers[i]
  705 |     |             );
  706 | *   |             emit SecondaryManagerRemoved(strategy, clearedSecondaryManagers[i]);
  707 |     |         }
  708 |     | 
  709 |     |         // Set the new primary manager
  710 | *   |         _strategyData[strategy].mainManager = newManager;
  711 |     | 
  712 | *   |         emit PrimaryManagerChanged(strategy, oldManager, newManager);
  713 |     |     }
  714 |     | 
  715 |     |     /// @inheritdoc ISuperVaultAggregator
  716 | *   |     function proposeChangePrimaryManager(
  717 |     |         address strategy,
  718 |     |         address newManager
  719 | *   |     ) external validStrategy(strategy) {
  720 |     |         // Only secondary managers can propose changes to the primary manager
  721 | *   |         if (!_strategyData[strategy].secondaryManagers.contains(msg.sender)) {
  722 | *   |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  723 |     |         }
  724 |     | 
  725 |     |         if (newManager == address(0)) revert ZERO_ADDRESS();
  726 |     | 
  727 |     |         // Set up the proposal with 7-day timelock
  728 |     |         uint256 effectiveTime = block.timestamp + _MANAGER_CHANGE_TIMELOCK;
  729 |     | 
  730 |     |         // Store proposal in the strategy data
  731 |     |         _strategyData[strategy].proposedManager = newManager;
  732 |     |         _strategyData[strategy].managerChangeEffectiveTime = effectiveTime;
  733 |     | 
  734 |     |         emit PrimaryManagerChangeProposed(
  735 |     |             strategy,
  736 |     |             msg.sender,
  737 |     |             newManager,
  738 |     |             effectiveTime
  739 |     |         );
  740 |     |     }
  741 |     | 
  742 |     |     /// @inheritdoc ISuperVaultAggregator
  743 | *   |     function executeChangePrimaryManager(
  744 |     |         address strategy
  745 | *   |     ) external validStrategy(strategy) {
  746 |     |         // Check if there is a pending proposal
  747 | *   |         if (_strategyData[strategy].proposedManager == address(0))
  748 | *   |             revert NO_PENDING_MANAGER_CHANGE();
  749 |     | 
  750 |     |         // Check if the timelock period has passed
  751 |     |         if (
  752 |     |             block.timestamp < _strategyData[strategy].managerChangeEffectiveTime
  753 |     |         ) revert TIMELOCK_NOT_EXPIRED();
  754 |     | 
  755 |     |         address newManager = _strategyData[strategy].proposedManager;
  756 |     |         address oldManager = _strategyData[strategy].mainManager;
  757 |     | 
  758 |     |         // If new manager is already a secondary manager, remove them
  759 |     |         _strategyData[strategy].secondaryManagers.remove(newManager);
  760 |     | 
  761 |     |         // Make the old primary manager a secondary manager
  762 |     |         if (
  763 |     |             _strategyData[strategy].secondaryManagers.length() <
  764 |     |             MAX_SECONDARY_MANAGERS
  765 |     |         ) {
  766 |     |             _strategyData[strategy].secondaryManagers.add(oldManager);
  767 |     |         }
  768 |     | 
  769 |     |         // Set the new primary manager
  770 |     |         _strategyData[strategy].mainManager = newManager;
  771 |     | 
  772 |     |         // Clear the proposal
  773 |     |         _strategyData[strategy].proposedManager = address(0);
  774 |     | 
  775 |     |         emit PrimaryManagerChanged(strategy, oldManager, newManager);
  776 |     |     }
  777 |     | 
  778 |     |     /*//////////////////////////////////////////////////////////////
  779 |     |                         HOOK VALIDATION FUNCTIONS
  780 |     |     //////////////////////////////////////////////////////////////*/
  781 |     |     /// @inheritdoc ISuperVaultAggregator
  782 |     |     function setHooksRootUpdateTimelock(uint256 newTimelock) external {
  783 |     |         // Only SUPER_GOVERNOR can update the timelock
  784 |     |         if (msg.sender != address(SUPER_GOVERNOR)) {
  785 |     |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  786 |     |         }
  787 |     | 
  788 |     |         // Update the timelock
  789 |     |         _hooksRootUpdateTimelock = newTimelock;
  790 |     | 
  791 |     |         emit HooksRootUpdateTimelockChanged(newTimelock);
  792 |     |     }
  793 |     | 
  794 |     |     /// @inheritdoc ISuperVaultAggregator
  795 | *   |     function proposeGlobalHooksRoot(bytes32 newRoot) external {
  796 |     |         // Only SUPER_GOVERNOR can update the global hooks root
  797 | *   |         if (msg.sender != address(SUPER_GOVERNOR)) {
  798 |     |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  799 |     |         }
  800 |     | 
  801 |     |         // Set new root with timelock
  802 | *   |         _proposedGlobalHooksRoot = newRoot;
  803 | *   |         uint256 effectiveTime = block.timestamp + _hooksRootUpdateTimelock;
  804 | *   |         _globalHooksRootEffectiveTime = effectiveTime;
  805 |     | 
  806 | *   |         emit GlobalHooksRootUpdateProposed(newRoot, effectiveTime);
  807 |     |     }
  808 |     | 
  809 |     |     /// @inheritdoc ISuperVaultAggregator
  810 | *   |     function executeGlobalHooksRootUpdate() external {
  811 |     |         bytes32 proposedRoot = _proposedGlobalHooksRoot;
  812 |     |         // Ensure there is a pending proposal
  813 |     |         if (proposedRoot == bytes32(0)) {
  814 |     |             revert NO_PENDING_GLOBAL_ROOT_CHANGE();
  815 |     |         }
  816 |     | 
  817 |     |         // Check if timelock period has elapsed
  818 |     |         if (block.timestamp < _globalHooksRootEffectiveTime) {
  819 |     |             revert ROOT_UPDATE_NOT_READY();
  820 |     |         }
  821 |     | 
  822 |     |         // Update the global hooks root
  823 |     |         bytes32 oldRoot = _globalHooksRoot;
  824 |     |         _globalHooksRoot = _proposedGlobalHooksRoot;
  825 |     |         _globalHooksRootEffectiveTime = 0;
  826 |     |         _proposedGlobalHooksRoot = bytes32(0);
  827 |     | 
  828 | *   |         emit GlobalHooksRootUpdated(oldRoot, proposedRoot);
  829 |     |     }
  830 |     | 
  831 |     |     /// @inheritdoc ISuperVaultAggregator
  832 |     |     function setGlobalHooksRootVetoStatus(bool vetoed) external {
  833 |     |         // Only SuperGovernor can call this
  834 |     |         if (msg.sender != address(SUPER_GOVERNOR)) {
  835 |     |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  836 |     |         }
  837 |     | 
  838 |     |         // Don't emit event if status doesn't change
  839 |     |         if (_globalHooksRootVetoed == vetoed) {
  840 |     |             return;
  841 |     |         }
  842 |     | 
  843 |     |         // Update veto status
  844 |     |         _globalHooksRootVetoed = vetoed;
  845 |     | 
  846 |     |         emit GlobalHooksRootVetoStatusChanged(vetoed, _globalHooksRoot);
  847 |     |     }
  848 |     | 
  849 |     |     /// @inheritdoc ISuperVaultAggregator
  850 |     |     function proposeStrategyHooksRoot(
  851 |     |         address strategy,
  852 |     |         bytes32 newRoot
  853 |     |     ) external validStrategy(strategy) {
  854 |     |         // Only the main manager can propose strategy-specific hooks root
  855 |     |         if (_strategyData[strategy].mainManager != msg.sender) {
  856 |     |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  857 |     |         }
  858 |     | 
  859 |     |         // Set proposed root with timelock
  860 |     |         _strategyData[strategy].proposedHooksRoot = newRoot;
  861 |     |         uint256 effectiveTime = block.timestamp + _hooksRootUpdateTimelock;
  862 |     |         _strategyData[strategy].hooksRootEffectiveTime = effectiveTime;
  863 |     | 
  864 |     |         emit StrategyHooksRootUpdateProposed(
  865 |     |             strategy,
  866 |     |             msg.sender,
  867 |     |             newRoot,
  868 |     |             effectiveTime
  869 |     |         );
  870 |     |     }
  871 |     | 
  872 |     |     /// @inheritdoc ISuperVaultAggregator
  873 |     |     function executeStrategyHooksRootUpdate(
  874 |     |         address strategy
  875 |     |     ) external validStrategy(strategy) {
  876 |     |         bytes32 proposedRoot = _strategyData[strategy].proposedHooksRoot;
  877 |     |         // Ensure there is a pending proposal
  878 |     |         if (proposedRoot == bytes32(0)) {
  879 |     |             revert NO_PENDING_MANAGER_CHANGE(); // Reusing error for simplicity
  880 |     |         }
  881 |     | 
  882 |     |         // Check if timelock period has elapsed
  883 |     |         if (block.timestamp < _strategyData[strategy].hooksRootEffectiveTime) {
  884 |     |             revert ROOT_UPDATE_NOT_READY();
  885 |     |         }
  886 |     | 
  887 |     |         // Update the strategy's hooks root
  888 |     |         bytes32 oldRoot = _strategyData[strategy].managerHooksRoot;
  889 |     |         _strategyData[strategy].managerHooksRoot = proposedRoot;
  890 |     | 
  891 |     |         // Reset proposal state
  892 |     |         _strategyData[strategy].proposedHooksRoot = bytes32(0);
  893 |     |         _strategyData[strategy].hooksRootEffectiveTime = 0;
  894 |     | 
  895 |     |         emit StrategyHooksRootUpdated(strategy, oldRoot, proposedRoot);
  896 |     |     }
  897 |     | 
  898 |     |     /// @inheritdoc ISuperVaultAggregator
  899 | *   |     function setStrategyHooksRootVetoStatus(
  900 |     |         address strategy,
  901 |     |         bool vetoed
  902 |     |     ) external validStrategy(strategy) {
  903 |     |         // Only SuperGovernor can call this
  904 |     |         if (msg.sender != address(SUPER_GOVERNOR)) {
  905 |     |             revert UNAUTHORIZED_UPDATE_AUTHORITY();
  906 |     |         }
  907 |     | 
  908 |     |         // Don't emit event if status doesn't change
  909 |     |         if (_strategyData[strategy].hooksRootVetoed == vetoed) {
  910 |     |             return;
  911 |     |         }
  912 |     | 
  913 |     |         // Update veto status
  914 |     |         _strategyData[strategy].hooksRootVetoed = vetoed;
  915 |     | 
  916 |     |         emit StrategyHooksRootVetoStatusChanged(
  917 |     |             strategy,
  918 |     |             vetoed,
  919 |     |             _strategyData[strategy].managerHooksRoot
  920 |     |         );
  921 |     |     }
  922 |     |     /// @inheritdoc ISuperVaultAggregator
  923 |     | 
  924 | *   |     function isGlobalHooksRootVetoed() external view returns (bool vetoed) {
  925 | *   |         return _globalHooksRootVetoed;
  926 |     |     }
  927 |     | 
  928 |     |     /// @inheritdoc ISuperVaultAggregator
  929 |     |     function isStrategyHooksRootVetoed(
  930 |     |         address strategy
  931 |     |     ) external view returns (bool vetoed) {
  932 |     |         return _strategyData[strategy].hooksRootVetoed;
  933 |     |     }
  934 |     | 
  935 |     |     /*//////////////////////////////////////////////////////////////
  936 |     |                               VIEW FUNCTIONS
  937 |     |     //////////////////////////////////////////////////////////////*/
  938 |     | 
  939 |     |     /// @inheritdoc ISuperVaultAggregator
  940 |     |     function getCurrentNonce() external view returns (uint256) {
  941 |     |         return _vaultCreationNonce;
  942 |     |     }
  943 |     | 
  944 |     |     /// @inheritdoc ISuperVaultAggregator
  945 |     |     function getHooksRootUpdateTimelock() external view returns (uint256) {
  946 |     |         return _hooksRootUpdateTimelock;
  947 |     |     }
  948 |     | 
  949 |     |     /// @inheritdoc ISuperVaultAggregator
  950 | *   |     function getPPS(
  951 |     |         address strategy
  952 | *   |     ) external view validStrategy(strategy) returns (uint256 pps) {
  953 | *   |         return _strategyData[strategy].pps;
  954 |     |     }
  955 |     | 
  956 |     |     /// @inheritdoc ISuperVaultAggregator
  957 |     |     function getPPSWithStdDev(
  958 |     |         address strategy
  959 |     |     )
  960 |     |         external
  961 |     |         view
  962 |     |         validStrategy(strategy)
  963 |     |         returns (uint256 pps, uint256 ppsStdev)
  964 |     |     {
  965 |     |         return (_strategyData[strategy].pps, _strategyData[strategy].ppsStdev);
  966 |     |     }
  967 |     | 
  968 |     |     /// @inheritdoc ISuperVaultAggregator
  969 |     |     function getLastUpdateTimestamp(
  970 |     |         address strategy
  971 |     |     ) external view returns (uint256 timestamp) {
  972 |     |         return _strategyData[strategy].lastUpdateTimestamp;
  973 |     |     }
  974 |     | 
  975 |     |     /// @inheritdoc ISuperVaultAggregator
  976 |     |     function getMinUpdateInterval(
  977 |     |         address strategy
  978 |     |     ) external view returns (uint256 interval) {
  979 |     |         return _strategyData[strategy].minUpdateInterval;
  980 |     |     }
  981 |     | 
  982 |     |     /// @inheritdoc ISuperVaultAggregator
  983 |     |     function getMaxStaleness(
  984 |     |         address strategy
  985 |     |     ) external view returns (uint256 staleness) {
  986 |     |         return _strategyData[strategy].maxStaleness;
  987 |     |     }
  988 |     | 
  989 |     |     /// @inheritdoc ISuperVaultAggregator
  990 |     |     function getPPSVerificationThresholds(
  991 |     |         address strategy
  992 |     |     )
  993 |     |         external
  994 |     |         view
  995 |     |         validStrategy(strategy)
  996 |     |         returns (
  997 |     |             uint256 dispersionThreshold,
  998 |     |             uint256 deviationThreshold,
  999 |     |             uint256 mnThreshold
 1000 |     |         )
 1001 |     |     {
 1002 |     |         return (
 1003 |     |             _strategyData[strategy].dispersionThreshold,
 1004 |     |             _strategyData[strategy].deviationThreshold,
 1005 |     |             _strategyData[strategy].mnThreshold
 1006 |     |         );
 1007 |     |     }
 1008 |     | 
 1009 |     |     /// @inheritdoc ISuperVaultAggregator
 1010 | *   |     function isStrategyPaused(
 1011 |     |         address strategy
 1012 | *   |     ) external view returns (bool isPaused) {
 1013 | *   |         return _strategyData[strategy].isPaused;
 1014 |     |     }
 1015 |     | 
 1016 |     |     /// @inheritdoc ISuperVaultAggregator
 1017 |     |     function getUpkeepBalance(
 1018 |     |         address manager
 1019 |     |     ) external view returns (uint256 balance) {
 1020 |     |         return _managerUpkeepBalance[manager];
 1021 |     |     }
 1022 |     | 
 1023 |     |     /// @notice Gets the current stake balance for a manager
 1024 |     |     /// @param manager Address of the manager
 1025 |     |     /// @return balance Current stake balance in UP tokens
 1026 |     |     function getStakeBalance(
 1027 |     |         address manager
 1028 |     |     ) external view returns (uint256 balance) {
 1029 |     |         return _managerStakeBalance[manager];
 1030 |     |     }
 1031 |     | 
 1032 |     |     /// @inheritdoc ISuperVaultAggregator
 1033 |     |     function getAuthorizedCallers(
 1034 |     |         address strategy
 1035 |     |     ) external view returns (address[] memory callers) {
 1036 |     |         return _strategyData[strategy].authorizedCallers.values();
 1037 |     |     }
 1038 |     | 
 1039 |     |     /// @inheritdoc ISuperVaultAggregator
 1040 |     |     function getMainManager(
 1041 |     |         address strategy
 1042 |     |     ) external view returns (address manager) {
 1043 |     |         manager = _strategyData[strategy].mainManager;
 1044 |     |         if (manager == address(0)) revert ZERO_ADDRESS();
 1045 |     | 
 1046 |     |         return manager;
 1047 |     |     }
 1048 |     | 
 1049 |     |     /// @inheritdoc ISuperVaultAggregator
 1050 | *   |     function isMainManager(
 1051 |     |         address manager,
 1052 |     |         address strategy
 1053 | *   |     ) external view returns (bool) {
 1054 | *   |         return _strategyData[strategy].mainManager == manager;
 1055 |     |     }
 1056 |     | 
 1057 |     |     /// @inheritdoc ISuperVaultAggregator
 1058 |     |     function getSecondaryManagers(
 1059 |     |         address strategy
 1060 |     |     ) external view returns (address[] memory) {
 1061 |     |         return _strategyData[strategy].secondaryManagers.values();
 1062 |     |     }
 1063 |     | 
 1064 |     |     /// @inheritdoc ISuperVaultAggregator
 1065 |     |     function isSecondaryManager(
 1066 |     |         address manager,
 1067 |     |         address strategy
 1068 |     |     ) external view returns (bool) {
 1069 |     |         return _strategyData[strategy].secondaryManagers.contains(manager);
 1070 |     |     }
 1071 |     | 
 1072 |     |     /// @inheritdoc ISuperVaultAggregator
 1073 | *   |     function isAnyManager(
 1074 |     |         address manager,
 1075 |     |         address strategy
 1076 | *   |     ) public view returns (bool) {
 1077 |     |         // Check if primary manager
 1078 | *   |         if (_strategyData[strategy].mainManager == manager) {
 1079 | *   |             return true;
 1080 |     |         }
 1081 |     | 
 1082 |     |         // Check if secondary manager using EnumerableSet
 1083 | *   |         return _strategyData[strategy].secondaryManagers.contains(manager);
 1084 |     |     }
 1085 |     | 
 1086 |     |     /// @inheritdoc ISuperVaultAggregator
 1087 |     |     function getAllSuperVaults() external view returns (address[] memory) {
 1088 |     |         return _superVaults.values();
 1089 |     |     }
 1090 |     | 
 1091 |     |     /// @inheritdoc ISuperVaultAggregator
 1092 | *   |     function superVaults(uint256 index) external view returns (address) {
 1093 |     |         if (index >= _superVaults.length()) revert INDEX_OUT_OF_BOUNDS();
 1094 | *   |         return _superVaults.at(index);
 1095 |     |     }
 1096 |     | 
 1097 |     |     /// @inheritdoc ISuperVaultAggregator
 1098 |     |     function getAllSuperVaultStrategies()
 1099 |     |         external
 1100 |     |         view
 1101 |     |         returns (address[] memory)
 1102 |     |     {
 1103 |     |         return _superVaultStrategies.values();
 1104 |     |     }
 1105 |     | 
 1106 |     |     /// @inheritdoc ISuperVaultAggregator
 1107 |     |     function superVaultStrategies(
 1108 |     |         uint256 index
 1109 |     |     ) external view returns (address) {
 1110 |     |         if (index >= _superVaultStrategies.length())
 1111 |     |             revert INDEX_OUT_OF_BOUNDS();
 1112 |     |         return _superVaultStrategies.at(index);
 1113 |     |     }
 1114 |     | 
 1115 |     |     /// @inheritdoc ISuperVaultAggregator
 1116 | *   |     function getAllSuperVaultEscrows()
 1117 |     |         external
 1118 |     |         view
 1119 |     |         returns (address[] memory)
 1120 |     |     {
 1121 | *   |         return _superVaultEscrows.values();
 1122 |     |     }
 1123 |     | 
 1124 |     |     /// @inheritdoc ISuperVaultAggregator
 1125 |     |     function superVaultEscrows(uint256 index) external view returns (address) {
 1126 |     |         if (index >= _superVaultEscrows.length()) revert INDEX_OUT_OF_BOUNDS();
 1127 |     |         return _superVaultEscrows.at(index);
 1128 |     |     }
 1129 |     | 
 1130 |     |     /// @inheritdoc ISuperVaultAggregator
 1131 |     |     function validateHook(
 1132 |     |         address strategy,
 1133 |     |         ValidateHookArgs calldata args
 1134 |     |     ) external view virtual returns (bool isValid) {
 1135 |     |         // Cache all state variables in struct
 1136 |     |         HookValidationCache memory cache = HookValidationCache({
 1137 |     |             globalHooksRootVetoed: _globalHooksRootVetoed,
 1138 |     |             globalHooksRoot: _globalHooksRoot,
 1139 |     |             strategyHooksRootVetoed: _strategyData[strategy].hooksRootVetoed,
 1140 |     |             strategyRoot: _strategyData[strategy].managerHooksRoot
 1141 |     |         });
 1142 |     | 
 1143 |     |         // Early return false if either global or strategy hooks root is vetoed
 1144 |     |         if (cache.globalHooksRootVetoed || cache.strategyHooksRootVetoed) {
 1145 |     |             return false;
 1146 |     |         }
 1147 |     | 
 1148 |     |         // Try to validate against global root first
 1149 |     |         if (
 1150 |     |             _validateSingleHook(
 1151 |     |                 args.hookAddress,
 1152 |     |                 args.hookArgs,
 1153 |     |                 args.globalProof,
 1154 |     |                 true,
 1155 |     |                 cache,
 1156 |     |                 strategy
 1157 |     |             )
 1158 |     |         ) {
 1159 |     |             return true;
 1160 |     |         }
 1161 |     | 
 1162 |     |         // If global validation fails, try strategy root
 1163 |     |         return
 1164 |     |             _validateSingleHook(
 1165 |     |                 args.hookAddress,
 1166 |     |                 args.hookArgs,
 1167 |     |                 args.strategyProof,
 1168 |     |                 false,
 1169 |     |                 cache,
 1170 |     |                 strategy
 1171 |     |             );
 1172 |     |     }
 1173 |     | 
 1174 |     |     /// @inheritdoc ISuperVaultAggregator
 1175 | *   |     function validateHooks(
 1176 |     |         address strategy,
 1177 |     |         ValidateHookArgs[] calldata argsArray
 1178 |     |     ) external view returns (bool[] memory validHooks) {
 1179 |     |         uint256 length = argsArray.length;
 1180 |     | 
 1181 |     |         // Cache all state variables in struct
 1182 |     |         HookValidationCache memory cache = HookValidationCache({
 1183 |     |             globalHooksRootVetoed: _globalHooksRootVetoed,
 1184 |     |             globalHooksRoot: _globalHooksRoot,
 1185 |     |             strategyHooksRootVetoed: _strategyData[strategy].hooksRootVetoed,
 1186 |     |             strategyRoot: _strategyData[strategy].managerHooksRoot
 1187 |     |         });
 1188 |     | 
 1189 |     |         // Early return all false if either global or strategy hooks root is vetoed
 1190 |     |         if (cache.globalHooksRootVetoed || cache.strategyHooksRootVetoed) {
 1191 |     |             return new bool[](length); // Array initialized with all false values
 1192 |     |         }
 1193 |     | 
 1194 |     |         // Validate each hook
 1195 |     |         validHooks = new bool[](length);
 1196 |     |         for (uint256 i; i < length; i++) {
 1197 |     |             // Try global root first
 1198 |     |             if (
 1199 |     |                 _validateSingleHook(
 1200 |     |                     argsArray[i].hookAddress,
 1201 |     |                     argsArray[i].hookArgs,
 1202 |     |                     argsArray[i].globalProof,
 1203 |     |                     true,
 1204 |     |                     cache,
 1205 |     |                     strategy
 1206 |     |                 )
 1207 |     |             ) {
 1208 |     |                 validHooks[i] = true;
 1209 |     |             } else {
 1210 |     |                 // Try strategy root
 1211 |     |                 validHooks[i] = _validateSingleHook(
 1212 |     |                     argsArray[i].hookAddress,
 1213 |     |                     argsArray[i].hookArgs,
 1214 |     |                     argsArray[i].strategyProof,
 1215 |     |                     false,
 1216 |     |                     cache,
 1217 |     |                     strategy
 1218 |     |                 );
 1219 |     |             }
 1220 |     |             // If both conditions fail, validHooks[i] remains false (default value)
 1221 |     |         }
 1222 |     | 
 1223 |     |         return validHooks;
 1224 |     |     }
 1225 |     | 
 1226 |     |     /// @inheritdoc ISuperVaultAggregator
 1227 |     |     function getGlobalHooksRoot() external view returns (bytes32 root) {
 1228 |     |         return _globalHooksRoot;
 1229 |     |     }
 1230 |     | 
 1231 |     |     /// @inheritdoc ISuperVaultAggregator
 1232 |     |     function getProposedGlobalHooksRoot()
 1233 |     |         external
 1234 |     |         view
 1235 |     |         returns (bytes32 root, uint256 effectiveTime)
 1236 |     |     {
 1237 |     |         return (_proposedGlobalHooksRoot, _globalHooksRootEffectiveTime);
 1238 |     |     }
 1239 |     | 
 1240 |     |     /// @notice Checks if the global hooks root is active (timelock period has passed)
 1241 |     |     /// @return isActive True if the global hooks root is active
 1242 | *   |     function isGlobalHooksRootActive() external view returns (bool) {
 1243 |     |         return
 1244 |     |             block.timestamp >= _globalHooksRootEffectiveTime &&
 1245 |     |             _globalHooksRoot != bytes32(0);
 1246 |     |     }
 1247 |     | 
 1248 |     |     /// @inheritdoc ISuperVaultAggregator
 1249 |     |     function getStrategyHooksRoot(
 1250 |     |         address strategy
 1251 |     |     ) external view returns (bytes32 root) {
 1252 |     |         return _strategyData[strategy].managerHooksRoot;
 1253 |     |     }
 1254 |     | 
 1255 |     |     /// @inheritdoc ISuperVaultAggregator
 1256 |     |     function getProposedStrategyHooksRoot(
 1257 |     |         address strategy
 1258 |     |     ) external view returns (bytes32 root, uint256 effectiveTime) {
 1259 |     |         return (
 1260 |     |             _strategyData[strategy].proposedHooksRoot,
 1261 |     |             _strategyData[strategy].hooksRootEffectiveTime
 1262 |     |         );
 1263 |     |     }
 1264 |     | 
 1265 |     |     /*//////////////////////////////////////////////////////////////
 1266 |     |                          INTERNAL HELPER FUNCTIONS
 1267 |     |     //////////////////////////////////////////////////////////////*/
 1268 |     |     /// @notice Internal implementation of forwarding PPS updates
 1269 |     |     /// @param args Struct containing all parameters for PPS update
 1270 | *   |     function _forwardPPS(PPSUpdateData memory args) internal {
 1271 |     |         // Check rate limiting
 1272 | *   |         uint256 minInterval = _strategyData[args.strategy].minUpdateInterval;
 1273 | *   |         uint256 lastUpdate = _strategyData[args.strategy].lastUpdateTimestamp;
 1274 | *   |         if (block.timestamp - lastUpdate < minInterval) {
 1275 | *   |             emit UpdateTooFrequent();
 1276 | *   |             return;
 1277 |     |         }
 1278 |     | 
 1279 |     |         // Ensure timestamp is monotonically increasing to prevent out-of-order updates
 1280 | *   |         if (args.timestamp <= lastUpdate) {
 1281 |     |             emit TimestampNotMonotonic();
 1282 |     |             return;
 1283 |     |         }
 1284 |     | 
 1285 |     |         // Get the strategy's manager to deduct upkeep cost from
 1286 | *   |         address manager = _strategyData[args.strategy].mainManager;
 1287 |     | 
 1288 |     |         // Flag to track if any check failed
 1289 |     |         bool checksFailed = false;
 1290 |     | 
 1291 |     |         // C2.1) Dispersion Check: Check if the standard deviation is too high relative to mean
 1292 | *   |         if (
 1293 | *   |             _strategyData[args.strategy].dispersionThreshold !=
 1294 |     |             type(uint256).max &&
 1295 | *   |             args.pps > 0
 1296 | *   |         ) {
 1297 |     |             // Calculate dispersion as stddev/mean
 1298 | *   |             uint256 dispersion = (args.ppsStdev * 1e18) / args.pps; // Scaled by 1e18 for precision
 1299 | *   |             if (dispersion > _strategyData[args.strategy].dispersionThreshold) {
 1300 |     |                 checksFailed = true;
 1301 |     |                 emit StrategyCheckFailed(args.strategy, "HIGH_PPS_DISPERSION");
 1302 |     |             }
 1303 |     |         }
 1304 |     | 
 1305 |     |         // C2.2) Deviation Check: Check if new PPS deviates too much from current PPS
 1306 | *   |         uint256 currentPPS = _strategyData[args.strategy].pps;
 1307 | *   |         if (
 1308 | *   |             _strategyData[args.strategy].deviationThreshold !=
 1309 |     |             type(uint256).max &&
 1310 | *   |             currentPPS > 0
 1311 | *   |         ) {
 1312 |     |             // Calculate absolute deviation, scaled by 1e18
 1313 | *   |             uint256 absDiff = args.pps > currentPPS
 1314 | *   |                 ? (args.pps - currentPPS)
 1315 | *   |                 : (currentPPS - args.pps);
 1316 | *   |             uint256 relativeDeviation = (absDiff * 1e18) / currentPPS;
 1317 | *   |             if (
 1318 | *   |                 relativeDeviation >
 1319 | *   |                 _strategyData[args.strategy].deviationThreshold
 1320 |     |             ) {
 1321 | *   |                 checksFailed = true;
 1322 | *   |                 emit StrategyCheckFailed(args.strategy, "HIGH_PPS_DEVIATION");
 1323 |     |             }
 1324 |     |         }
 1325 |     | 
 1326 |     |         // C2.3) M/N Check: Check if enough validators participated
 1327 | *   |         if (
 1328 | *   |             args.totalValidators > 0 &&
 1329 |     |             _strategyData[args.strategy].mnThreshold > 0
 1330 |     |         ) {
 1331 |     |             // Calculate participation rate, scaled by 1e18
 1332 |     |             uint256 participationRate = (args.validatorSet * 1e18) /
 1333 |     |                 args.totalValidators;
 1334 |     |             if (participationRate < _strategyData[args.strategy].mnThreshold) {
 1335 |     |                 checksFailed = true;
 1336 |     |                 emit StrategyCheckFailed(
 1337 |     |                     args.strategy,
 1338 |     |                     "INSUFFICIENT_VALIDATOR_PARTICIPATION"
 1339 |     |                 );
 1340 |     |             }
 1341 |     |         }
 1342 |     | 
 1343 |     |         // Pause strategy if any check failed
 1344 | *   |         if (checksFailed && !_strategyData[args.strategy].isPaused) {
 1345 | *   |             _strategyData[args.strategy].isPaused = true;
 1346 | *   |             emit StrategyPaused(args.strategy);
 1347 |     |         }
 1348 |     |         // Unpause strategy if all checks passed and strategy was previously paused
 1349 | *   |         else if (!checksFailed && _strategyData[args.strategy].isPaused) {
 1350 | *   |             _strategyData[args.strategy].isPaused = false;
 1351 | *   |             emit StrategyUnpaused(args.strategy);
 1352 |     |         }
 1353 |     | 
 1354 |     |         // Handle upkeep costs unless exempt
 1355 | *   |         if (!args.isExempt) {
 1356 |     |             // Check if manager has sufficient upkeep balance
 1357 |     |             if (_managerUpkeepBalance[manager] < args.upkeepCost) {
 1358 |     |                 emit InsufficientUpkeep(
 1359 |     |                     args.strategy,
 1360 |     |                     manager,
 1361 |     |                     _managerUpkeepBalance[manager],
 1362 |     |                     args.upkeepCost
 1363 |     |                 );
 1364 |     |                 return;
 1365 |     |             }
 1366 |     | 
 1367 |     |             // Deduct the upkeep cost and emit event
 1368 |     |             _managerUpkeepBalance[manager] -= args.upkeepCost;
 1369 |     | 
 1370 |     |             // Add claimable upkeep for the `feeRecipient`
 1371 |     |             claimableUpkeep += args.upkeepCost;
 1372 |     | 
 1373 |     |             emit UpkeepSpent(manager, args.upkeepCost);
 1374 |     |         }
 1375 |     | 
 1376 |     |         // Update PPS, ppsStdev and timestamp in StrategyData
 1377 | *   |         _strategyData[args.strategy].pps = args.pps;
 1378 | *   |         _strategyData[args.strategy].ppsStdev = args.ppsStdev;
 1379 | *   |         _strategyData[args.strategy].lastUpdateTimestamp = args.timestamp;
 1380 |     | 
 1381 | *   |         emit PPSUpdated(
 1382 | *   |             args.strategy,
 1383 | *   |             args.pps,
 1384 | *   |             args.ppsStdev,
 1385 | *   |             args.validatorSet,
 1386 | *   |             args.totalValidators,
 1387 | *   |             args.timestamp
 1388 |     |         );
 1389 |     |     }
 1390 |     | 
 1391 |     |     /// @notice Check if an update authority is exempt from paying upkeep costs
 1392 |     |     /// @param strategy Address of the strategy being updated
 1393 |     |     /// @param updateAuthority Address initiating the update
 1394 |     |     /// @param timestamp Timestamp of the PPS measurement
 1395 |     |     /// @return isExempt True if the authority is exempt from paying upkeep
 1396 |     |     function _isExemptFromUpkeep(
 1397 |     |         address strategy,
 1398 |     |         address updateAuthority,
 1399 |     |         uint256 timestamp
 1400 |     |     ) internal returns (bool) {
 1401 |     |         // Check if upkeep payments are globally disabled in SuperGovernor
 1402 |     |         if (!SUPER_GOVERNOR.isUpkeepPaymentsEnabled()) {
 1403 |     |             return true;
 1404 |     |         }
 1405 |     | 
 1406 |     |         // Update is exempt if it is stale
 1407 |     |         if (
 1408 |     |             block.timestamp - timestamp > _strategyData[strategy].maxStaleness
 1409 |     |         ) {
 1410 |     |             emit StaleUpdate(strategy, updateAuthority, timestamp);
 1411 |     |             return true;
 1412 |     |         }
 1413 |     | 
 1414 |     |         // If manager is a superform manager, they're exempt from upkeep fees
 1415 |     |         address manager = _strategyData[strategy].mainManager;
 1416 |     |         if (SUPER_GOVERNOR.isSuperformManager(manager)) {
 1417 |     |             return true;
 1418 |     |         }
 1419 |     | 
 1420 |     |         // Check if the updateAuthority is in the authorized callers list
 1421 |     |         // These are manager-designated keepers that should be exempt from fees
 1422 |     |         // NOTE: Protected keepers cannot be added to this list (blocked in addAuthorizedCaller)
 1423 |     |         if (
 1424 |     |             _strategyData[strategy].authorizedCallers.contains(updateAuthority)
 1425 |     |         ) {
 1426 |     |             return true;
 1427 |     |         }
 1428 |     | 
 1429 |     |         return false;
 1430 |     |     }
 1431 |     | 
 1432 |     |     /// @notice Creates a leaf node for Merkle verification from hook address and arguments
 1433 |     |     /// @param hookAddress The address of the hook contract
 1434 |     |     /// @param hookArgs The packed-encoded hook arguments (from solidityPack in JS)
 1435 |     |     /// @return leaf The leaf node hash
 1436 |     |     function _createLeaf(
 1437 |     |         address hookAddress,
 1438 |     |         bytes calldata hookArgs
 1439 |     |     ) internal pure returns (bytes32) {
 1440 |     |         /// @dev The leaf now includes both hook address and args to prevent cross-hook replay attacks
 1441 |     |         /// @dev Different hooks with identical encoded args will have different authorization leaves
 1442 |     |         /// @dev This matches StandardMerkleTree's standardLeafHash: keccak256(keccak256(abi.encode(hookAddress,
 1443 |     |         /// hookArgs)))
 1444 |     |         /// @dev but uses bytes.concat for explicit concatenation
 1445 |     |         return
 1446 |     |             keccak256(
 1447 |     |                 bytes.concat(keccak256(abi.encode(hookAddress, hookArgs)))
 1448 |     |             );
 1449 |     |     }
 1450 |     | 
 1451 |     |     /**
 1452 |     |      * @dev Internal function to validate a single hook against either global or strategy root
 1453 |     |      * @param hookAddress The address of the hook contract
 1454 |     |      * @param hookArgs Hook arguments
 1455 |     |      * @param proof Merkle proof for the specified root
 1456 |     |      * @param isGlobalProof Whether to validate against global root (true) or strategy root (false)
 1457 |     |      * @param cache Cached hook validation state variables
 1458 |     |      * @param strategy Address of the strategy (needed to check banned leaves for global proofs)
 1459 |     |      * @return True if hook is valid, false otherwise
 1460 |     |      */
 1461 |     |     function _validateSingleHook(
 1462 |     |         address hookAddress,
 1463 |     |         bytes calldata hookArgs,
 1464 |     |         bytes32[] calldata proof,
 1465 |     |         bool isGlobalProof,
 1466 |     |         HookValidationCache memory cache,
 1467 |     |         address strategy
 1468 |     |     ) internal view returns (bool) {
 1469 |     |         // Create leaf node from the hook address and arguments
 1470 |     |         bytes32 leaf = _createLeaf(hookAddress, hookArgs);
 1471 |     | 
 1472 |     |         if (isGlobalProof) {
 1473 |     |             // Validate against global root
 1474 |     |             if (
 1475 |     |                 cache.globalHooksRootVetoed ||
 1476 |     |                 cache.globalHooksRoot == bytes32(0)
 1477 |     |             ) {
 1478 |     |                 return false;
 1479 |     |             }
 1480 |     | 
 1481 |     |             // Check if this leaf is banned by the manager
 1482 |     |             if (_strategyData[strategy].bannedLeaves[leaf]) {
 1483 |     |                 return false;
 1484 |     |             }
 1485 |     | 
 1486 |     |             // For single-leaf trees, empty proof is valid when root equals leaf
 1487 |     |             if (proof.length == 0) {
 1488 |     |                 return cache.globalHooksRoot == leaf;
 1489 |     |             }
 1490 |     |             return MerkleProof.verify(proof, cache.globalHooksRoot, leaf);
 1491 |     |         } else {
 1492 |     |             // Validate against strategy root
 1493 |     |             if (
 1494 |     |                 cache.strategyHooksRootVetoed ||
 1495 |     |                 cache.strategyRoot == bytes32(0)
 1496 |     |             ) {
 1497 |     |                 return false;
 1498 |     |             }
 1499 |     |             // For single-leaf trees, empty proof is valid when root equals leaf
 1500 |     |             if (proof.length == 0) {
 1501 |     |                 return cache.strategyRoot == leaf;
 1502 |     |             }
 1503 |     |             return MerkleProof.verify(proof, cache.strategyRoot, leaf);
 1504 |     |         }
 1505 |     |     }
 1506 |     | 
 1507 |     |     /**
 1508 |     |      * @dev Internal function to return the `SuperBank` address
 1509 |     |      * @return superBank The superBank address
 1510 |     |      */
 1511 | *   |     function _getSuperBank() internal view returns (address) {
 1512 | *   |         return SUPER_GOVERNOR.getAddress(SUPER_GOVERNOR.SUPER_BANK());
 1513 |     |     }
 1514 |     | }
 1515 |     | 

/opt/scfuzzbench/work/target/src/SuperVault/SuperVaultEscrow.sol
  1 |     | // SPDX-License-Identifier: UNLICENSED
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
  5 |     | import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
  6 |     | 
  7 |     | /// @title SuperVaultEscrow
  8 |     | /// @author Superform Labs
  9 |     | /// @notice Escrow contract for SuperVault shares during request/claim process
 10 | *   | contract SuperVaultEscrow {
 11 |     |     using SafeERC20 for IERC20;
 12 |     | 
 13 |     |     /*//////////////////////////////////////////////////////////////
 14 |     |                                 ERRORS
 15 |     |     //////////////////////////////////////////////////////////////*/
 16 |     |     error ALREADY_INITIALIZED();
 17 |     |     error UNAUTHORIZED();
 18 |     |     error ZERO_ADDRESS();
 19 |     | 
 20 |     |     /*//////////////////////////////////////////////////////////////
 21 |     |                                 STATE
 22 |     |     //////////////////////////////////////////////////////////////*/
 23 |     |     bool public initialized;
 24 |     |     address public vault;
 25 |     |     address public strategy;
 26 |     | 
 27 |     |     /*//////////////////////////////////////////////////////////////
 28 |     |                                 MODIFIERS
 29 |     |     //////////////////////////////////////////////////////////////*/
 30 |     |     modifier onlyVault() {
 31 | *   |         if (msg.sender != vault) revert UNAUTHORIZED();
 32 |     |         _;
 33 |     |     }
 34 |     | 
 35 |     |     /*//////////////////////////////////////////////////////////////
 36 |     |                             INITIALIZATION
 37 |     |     //////////////////////////////////////////////////////////////*/
 38 |     | 
 39 |     |     /// @notice Initialize the escrow with required parameters
 40 |     |     /// @param vaultAddress The vault contract address
 41 |     |     /// @param strategyAddress The strategy contract address
 42 | *   |     function initialize(address vaultAddress, address strategyAddress) external {
 43 | *   |         if (initialized) revert ALREADY_INITIALIZED();
 44 | *   |         if (vaultAddress == address(0) || strategyAddress == address(0)) revert ZERO_ADDRESS();
 45 |     | 
 46 | *   |         initialized = true;
 47 | *   |         vault = vaultAddress;
 48 | *   |         strategy = strategyAddress;
 49 |     |     }
 50 |     | 
 51 |     |     /*//////////////////////////////////////////////////////////////
 52 |     |                             VAULT FUNCTIONS
 53 |     |     //////////////////////////////////////////////////////////////*/
 54 |     | 
 55 |     |     /// @notice Transfer shares from user to escrow during redeem request
 56 |     |     /// @param from The address to transfer shares from
 57 |     |     /// @param amount The amount of shares to transfer
 58 | *   |     function escrowShares(address from, uint256 amount) external onlyVault {
 59 | *   |         IERC20(vault).safeTransferFrom(from, address(this), amount);
 60 |     |     }
 61 |     | 
 62 |     |     /// @notice Return shares from escrow to user during redeem cancellation
 63 |     |     /// @param to The address to return shares to
 64 |     |     /// @param amount The amount of shares to return
 65 | *   |     function returnShares(address to, uint256 amount) external onlyVault {
 66 | *   |         IERC20(vault).safeTransfer(to, amount);
 67 |     |     }
 68 |     | }
 69 |     | 

/opt/scfuzzbench/work/target/src/SuperVault/SuperVaultStrategy.sol
    1 |     | // SPDX-License-Identifier: UNLICENSED
    2 |     | pragma solidity 0.8.30;
    3 |     | 
    4 |     | // External
    5 |     | import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
    6 |     | import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
    7 |     | import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
    8 |     | import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
    9 |     | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   10 |     | import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
   11 |     | import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
   12 |     | import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
   13 |     | 
   14 |     | // Core Interfaces
   15 |     | import {ISuperHook, ISuperHookResult, ISuperHookOutflow, ISuperHookInflowOutflow, ISuperHookResultOutflow, ISuperHookContextAware, ISuperHookInspector} from "@superform-v2-core/src/interfaces/ISuperHook.sol";
   16 |     | import {IYieldSourceOracle} from "@superform-v2-core/src/interfaces/accounting/IYieldSourceOracle.sol";
   17 |     | 
   18 |     | // Periphery Interfaces
   19 |     | import {ISuperVault} from "../interfaces/SuperVault/ISuperVault.sol";
   20 |     | import {HookDataDecoder} from "@superform-v2-core/src/libraries/HookDataDecoder.sol";
   21 |     | import {ISuperVaultStrategy} from "../interfaces/SuperVault/ISuperVaultStrategy.sol";
   22 |     | import {ISuperGovernor, FeeType} from "../interfaces/ISuperGovernor.sol";
   23 |     | import {ISuperVaultAggregator} from "../interfaces/SuperVault/ISuperVaultAggregator.sol";
   24 |     | 
   25 |     | /// @title SuperVaultStrategy
   26 |     | /// @author Superform Labs
   27 |     | /// @notice Strategy implementation for SuperVault that executes strategies
   28 | *   | contract SuperVaultStrategy is
   29 |     |     ISuperVaultStrategy,
   30 |     |     Initializable,
   31 |     |     ReentrancyGuardUpgradeable
   32 |     | {
   33 |     |     using EnumerableSet for EnumerableSet.AddressSet;
   34 |     |     using SafeERC20 for IERC20;
   35 |     |     using Math for uint256;
   36 |     | 
   37 |     |     /*//////////////////////////////////////////////////////////////
   38 |     |                                 CONSTANTS
   39 |     |     //////////////////////////////////////////////////////////////*/
   40 | *   |     uint256 private constant ONE_WEEK = 7 days;
   41 | *   |     uint256 private constant BPS_PRECISION = 10_000;
   42 |     |     /// @dev The following is needed because the `processedShares` for some vaults (for example Centrifuge)
   43 |     |     ///      can be lower by 1 or 2 wei than the `totalRequestedAmount`in SuperVault shares
   44 | *   |     uint256 private constant TOLERANCE_CONSTANT = 10 wei;
   45 |     | 
   46 |     |     // Slippage tolerance in BPS (1%)
   47 | *   |     uint256 private constant SV_SLIPPAGE_TOLERANCE_BPS = 100;
   48 |     | 
   49 |     |     uint256 public PRECISION;
   50 |     | 
   51 |     |     /*//////////////////////////////////////////////////////////////
   52 |     |                                 STATE
   53 |     |     //////////////////////////////////////////////////////////////*/
   54 |     |     address private _vault;
   55 |     |     IERC20 private _asset;
   56 |     |     uint8 private _vaultDecimals;
   57 |     | 
   58 |     |     // Global configuration
   59 |     |     uint256 private _maxPPSSlippage;
   60 |     | 
   61 |     |     // Fee configuration
   62 |     |     FeeConfig private feeConfig;
   63 |     |     FeeConfig private proposedFeeConfig;
   64 |     |     uint256 private feeConfigEffectiveTime;
   65 |     | 
   66 |     |     // Core contracts
   67 |     |     ISuperGovernor public immutable superGovernor;
   68 |     | 
   69 |     |     // Emergency withdrawable configuration
   70 |     |     bool public emergencyWithdrawable;
   71 |     |     bool public proposedEmergencyWithdrawable;
   72 |     |     uint256 public emergencyWithdrawableEffectiveTime;
   73 |     | 
   74 |     |     // Yield source configuration - simplified mapping from source to oracle
   75 |     |     mapping(address source => address oracle) private yieldSources;
   76 |     |     EnumerableSet.AddressSet private yieldSourcesList;
   77 |     | 
   78 |     |     // --- Redeem Request State ---
   79 |     |     mapping(address controller => SuperVaultState state)
   80 |     |         private superVaultState;
   81 |     | 
   82 | *   |     constructor(address superGovernor_) {
   83 | *   |         if (superGovernor_ == address(0)) revert ZERO_ADDRESS();
   84 |     | 
   85 | *   |         superGovernor = ISuperGovernor(superGovernor_);
   86 | *   |         emit SuperGovernorSet(superGovernor_);
   87 | *   |         _disableInitializers();
   88 |     |     }
   89 |     | 
   90 |     |     /// @notice Allows the contract to receive native ETH
   91 |     |     /// @dev Required for hooks that may send ETH back to the strategy
   92 |     |     receive() external payable {}
   93 |     | 
   94 |     |     /*//////////////////////////////////////////////////////////////
   95 |     |                             INITIALIZATION
   96 |     |     //////////////////////////////////////////////////////////////*/
   97 | *   |     function initialize(
   98 |     |         address vaultAddress,
   99 |     |         FeeConfig memory feeConfigData
  100 |     |     ) external initializer {
  101 | *   |         if (vaultAddress == address(0)) revert INVALID_VAULT();
  102 |     |         // if either fee is configured, check if recipient is address (0), if it is revert with ZERO ADDRESS
  103 |     |         // if both fees are 0, no need check address (it just passes the if). Recipient can be configured later
  104 | *   |         if (
  105 | *   |             (feeConfigData.performanceFeeBps > 0 ||
  106 | *   |                 feeConfigData.managementFeeBps > 0) &&
  107 | *   |             feeConfigData.recipient == address(0)
  108 |     |         ) revert ZERO_ADDRESS();
  109 | *   |         if (feeConfigData.performanceFeeBps > BPS_PRECISION)
  110 | *   |             revert INVALID_PERFORMANCE_FEE_BPS();
  111 | *   |         if (feeConfigData.managementFeeBps > BPS_PRECISION)
  112 | *   |             revert INVALID_PERFORMANCE_FEE_BPS();
  113 |     | 
  114 | *   |         __ReentrancyGuard_init();
  115 |     | 
  116 | *   |         _vault = vaultAddress;
  117 | *   |         _asset = IERC20(IERC4626(vaultAddress).asset());
  118 | *   |         _vaultDecimals = IERC20Metadata(vaultAddress).decimals();
  119 | *   |         PRECISION = 10 ** _vaultDecimals;
  120 | *   |         feeConfig = feeConfigData;
  121 | *   |         _maxPPSSlippage = 500; // 5% as a start, configurable later
  122 |     | 
  123 | *   |         emit Initialized(_vault);
  124 |     |     }
  125 |     | 
  126 |     |     /*//////////////////////////////////////////////////////////////
  127 |     |                         CORE STRATEGY OPERATIONS
  128 |     |     //////////////////////////////////////////////////////////////*/
  129 |     | 
  130 |     |     /// @inheritdoc ISuperVaultStrategy
  131 | *   |     function handleOperations4626Deposit(
  132 |     |         address controller,
  133 |     |         uint256 assetsGross
  134 | *   |     ) external returns (uint256 sharesNet) {
  135 | *   |         _requireVault();
  136 |     | 
  137 | *   |         if (assetsGross == 0) revert INVALID_AMOUNT();
  138 | *   |         if (controller == address(0)) revert ZERO_ADDRESS();
  139 |     | 
  140 |     |         // Check if strategy is paused or if global hooks root is vetoed
  141 | *   |         if (_isPaused()) revert STRATEGY_PAUSED();
  142 | *   |         if (_getSuperVaultAggregator().isGlobalHooksRootVetoed()) {
  143 |     |             revert OPERATIONS_BLOCKED_BY_VETO();
  144 |     |         }
  145 |     | 
  146 |     |         // Fee skim in ASSETS (asset-side entry fee)
  147 | *   |         uint256 feeBps = feeConfig.managementFeeBps;
  148 | *   |         uint256 feeAssets = feeBps == 0
  149 | *   |             ? 0
  150 | *   |             : Math.mulDiv(
  151 | *   |                 assetsGross,
  152 | *   |                 feeBps,
  153 |     |                 BPS_PRECISION,
  154 | *   |                 Math.Rounding.Ceil
  155 |     |             );
  156 |     | 
  157 | *   |         uint256 assetsNet = assetsGross - feeAssets;
  158 | *   |         if (assetsNet == 0) revert INVALID_AMOUNT();
  159 |     | 
  160 | *   |         if (feeAssets != 0) {
  161 | *   |             address recipient = feeConfig.recipient;
  162 | *   |             if (recipient == address(0)) revert ZERO_ADDRESS();
  163 | *   |             _safeTokenTransfer(address(_asset), recipient, feeAssets);
  164 | *   |             emit ManagementFeePaid(controller, recipient, feeAssets, feeBps);
  165 |     |         }
  166 |     | 
  167 |     |         // Compute shares on NET using current PPS
  168 | *   |         uint256 pps = getStoredPPS();
  169 | *   |         if (pps == 0) revert INVALID_PPS();
  170 | *   |         sharesNet = Math.mulDiv(assetsNet, PRECISION, pps, Math.Rounding.Floor);
  171 | *   |         if (sharesNet == 0) revert INVALID_AMOUNT();
  172 |     | 
  173 |     |         // Account on NET
  174 | *   |         SuperVaultState storage state = superVaultState[controller];
  175 | *   |         state.accumulatorShares += sharesNet;
  176 | *   |         state.accumulatorCostBasis += assetsNet;
  177 | *   |         emit DepositHandled(controller, assetsNet, sharesNet);
  178 | *   |         return sharesNet;
  179 |     |     }
  180 |     | 
  181 |     |     /// @inheritdoc ISuperVaultStrategy
  182 | *   |     function handleOperations4626Mint(
  183 |     |         address controller,
  184 |     |         uint256 sharesNet,
  185 |     |         uint256 assetsGross,
  186 |     |         uint256 assetsNet
  187 | *   |     ) external {
  188 | *   |         _requireVault();
  189 |     | 
  190 | *   |         if (sharesNet == 0) revert INVALID_AMOUNT();
  191 | *   |         if (controller == address(0)) revert ZERO_ADDRESS();
  192 |     | 
  193 |     |         // Check if strategy is paused or if global hooks root is vetoed
  194 | *   |         if (_isPaused()) revert STRATEGY_PAUSED();
  195 | *   |         if (_getSuperVaultAggregator().isGlobalHooksRootVetoed()) {
  196 |     |             revert OPERATIONS_BLOCKED_BY_VETO();
  197 |     |         }
  198 |     | 
  199 | *   |         uint256 feeBps = feeConfig.managementFeeBps;
  200 |     |         // Transfer fee if needed
  201 | *   |         if (feeBps != 0) {
  202 | *   |             uint256 feeAssets = assetsGross - assetsNet;
  203 | *   |             if (feeAssets != 0) {
  204 | *   |                 address recipient = feeConfig.recipient;
  205 | *   |                 if (recipient == address(0)) revert ZERO_ADDRESS();
  206 | *   |                 _safeTokenTransfer(address(_asset), recipient, feeAssets);
  207 | *   |                 emit ManagementFeePaid(
  208 | *   |                     controller,
  209 | *   |                     recipient,
  210 | *   |                     feeAssets,
  211 | *   |                     feeBps
  212 |     |                 );
  213 |     |             }
  214 |     |         }
  215 |     | 
  216 |     |         // Account on NET
  217 | *   |         SuperVaultState storage state = superVaultState[controller];
  218 | *   |         state.accumulatorShares += sharesNet;
  219 | *   |         state.accumulatorCostBasis += assetsNet;
  220 | *   |         emit DepositHandled(controller, assetsNet, sharesNet);
  221 |     |     }
  222 |     | 
  223 |     |     /// @inheritdoc ISuperVaultStrategy
  224 | *   |     function quoteMintAssetsGross(
  225 |     |         uint256 shares
  226 | *   |     ) external view returns (uint256 assetsGross, uint256 assetsNet) {
  227 | *   |         uint256 pps = getStoredPPS();
  228 | *   |         if (pps == 0) revert INVALID_PPS();
  229 | *   |         assetsNet = Math.mulDiv(shares, pps, PRECISION, Math.Rounding.Ceil);
  230 | *   |         if (assetsNet == 0) revert INVALID_AMOUNT();
  231 |     | 
  232 | *   |         uint256 feeBps = feeConfig.managementFeeBps;
  233 | *   |         if (feeBps == 0) return (assetsNet, assetsNet);
  234 | *   |         if (feeBps >= BPS_PRECISION) revert INVALID_AMOUNT(); // prevents div-by-zero (100% fee)
  235 | *   |         assetsGross = Math.mulDiv(
  236 | *   |             assetsNet,
  237 |     |             BPS_PRECISION,
  238 | *   |             (BPS_PRECISION - feeBps),
  239 | *   |             Math.Rounding.Ceil
  240 |     |         );
  241 | *   |         return (assetsGross, assetsNet);
  242 |     |     }
  243 |     | 
  244 |     |     /// @inheritdoc ISuperVaultStrategy
  245 | *   |     function handleOperations7540(
  246 |     |         Operation operation,
  247 |     |         address controller,
  248 |     |         address receiver,
  249 |     |         uint256 amount
  250 |     |     ) external {
  251 | *   |         _requireVault();
  252 | *   |         if (operation == Operation.RedeemRequest) {
  253 | *   |             _handleRequestRedeem(controller, amount); // amount = shares
  254 | *   |         } else if (operation == Operation.CancelRedeem) {
  255 | *   |             _handleCancelRedeem(controller);
  256 | *   |         } else if (operation == Operation.ClaimRedeem) {
  257 | *   |             _handleClaimRedeem(controller, receiver, amount); // amount = assets
  258 |     |         } else {
  259 | *   |             revert ACTION_TYPE_DISALLOWED();
  260 |     |         }
  261 |     |     }
  262 |     | 
  263 |     |     /*//////////////////////////////////////////////////////////////
  264 |     |                 MANAGER EXTERNAL ACCESS FUNCTIONS
  265 |     |     //////////////////////////////////////////////////////////////*/
  266 |     | 
  267 |     |     /// @inheritdoc ISuperVaultStrategy
  268 | *   |     function executeHooks(
  269 |     |         ExecuteArgs calldata args
  270 | *   |     ) external payable nonReentrant {
  271 | *   |         _isManager(msg.sender);
  272 |     | 
  273 | *   |         uint256 hooksLength = args.hooks.length;
  274 | *   |         if (hooksLength == 0) revert ZERO_LENGTH();
  275 | *   |         if (args.hookCalldata.length != hooksLength)
  276 | *   |             revert INVALID_ARRAY_LENGTH();
  277 | *   |         if (args.expectedAssetsOrSharesOut.length != hooksLength)
  278 | *   |             revert INVALID_ARRAY_LENGTH();
  279 | *   |         if (args.globalProofs.length != hooksLength)
  280 | *   |             revert INVALID_ARRAY_LENGTH();
  281 | *   |         if (args.strategyProofs.length != hooksLength)
  282 | *   |             revert INVALID_ARRAY_LENGTH();
  283 |     | 
  284 | *   |         address prevHook;
  285 | *   |         for (uint256 i; i < hooksLength; ++i) {
  286 | *   |             address hook = args.hooks[i];
  287 | *   |             if (!_isRegisteredHook(hook)) revert INVALID_HOOK();
  288 |     | 
  289 |     |             // Check if the hook was validated
  290 | *   |             if (
  291 | *   |                 !_validateHook(
  292 | *   |                     hook,
  293 | *   |                     args.hookCalldata[i],
  294 | *   |                     args.globalProofs[i],
  295 | *   |                     args.strategyProofs[i]
  296 |     |                 )
  297 |     |             ) {
  298 |     |                 revert HOOK_VALIDATION_FAILED();
  299 |     |             }
  300 |     | 
  301 | *   |             prevHook = _processSingleHookExecution(
  302 | *   |                 hook,
  303 | *   |                 prevHook,
  304 | *   |                 args.hookCalldata[i],
  305 | *   |                 args.expectedAssetsOrSharesOut[i]
  306 |     |             );
  307 |     |         }
  308 | *   |         emit HooksExecuted(args.hooks);
  309 |     |     }
  310 |     | 
  311 |     |     /// @inheritdoc ISuperVaultStrategy
  312 | *   |     function fulfillRedeemRequests(
  313 |     |         FulfillArgs calldata args
  314 | *   |     ) external nonReentrant {
  315 | *   |         _isManager(msg.sender);
  316 |     | 
  317 |     |         // Check if strategy is paused
  318 | *   |         if (_isPaused()) revert STRATEGY_PAUSED();
  319 |     | 
  320 | *   |         uint256 hooksLength = args.hooks.length;
  321 | *   |         if (hooksLength == 0) revert ZERO_LENGTH();
  322 | *   |         uint256 controllersLength = args.controllers.length;
  323 | *   |         if (controllersLength == 0) revert ZERO_LENGTH();
  324 | *   |         if (args.hookCalldata.length != hooksLength)
  325 | *   |             revert INVALID_ARRAY_LENGTH();
  326 | *   |         if (args.expectedAssetsOrSharesOut.length != hooksLength)
  327 | *   |             revert INVALID_ARRAY_LENGTH();
  328 | *   |         if (args.globalProofs.length != hooksLength)
  329 | *   |             revert INVALID_ARRAY_LENGTH();
  330 | *   |         if (args.strategyProofs.length != hooksLength)
  331 |     |             revert INVALID_ARRAY_LENGTH();
  332 |     | 
  333 | *   |         uint256 currentPPS = getStoredPPS();
  334 | *   |         if (currentPPS == 0) revert INVALID_PPS();
  335 |     | 
  336 |     |         // Pre-calculate totals to ensure no overburn of escrowed shares
  337 | *   |         uint256 totalRequestedShares;
  338 | *   |         for (uint256 i; i < controllersLength; ++i) {
  339 | *   |             totalRequestedShares += superVaultState[args.controllers[i]]
  340 |     |                 .pendingRedeemRequest;
  341 |     |         }
  342 | *   |         uint256 intendedShares;
  343 | *   |         for (uint256 i; i < hooksLength; ++i) {
  344 | *   |             address hook = args.hooks[i];
  345 | *   |             if (!_isFulfillRequestsHook(hook)) revert INVALID_HOOK();
  346 |     |             // Check if the hook was validated
  347 | *   |             if (
  348 | *   |                 !_validateHook(
  349 | *   |                     hook,
  350 | *   |                     args.hookCalldata[i],
  351 | *   |                     args.globalProofs[i],
  352 | *   |                     args.strategyProofs[i]
  353 |     |                 )
  354 |     |             ) {
  355 |     |                 revert HOOK_VALIDATION_FAILED();
  356 |     |             }
  357 | *   |             if (args.expectedAssetsOrSharesOut[i] == 0)
  358 | *   |                 revert ZERO_EXPECTED_VALUE();
  359 |     | 
  360 | *   |             intendedShares += ISuperHookInflowOutflow(hook).decodeAmount(
  361 | *   |                 args.hookCalldata[i]
  362 |     |             );
  363 |     |         }
  364 |     | 
  365 |     |         // Enforce both lower- and upper-bounds on intended shares to prevent escrow overburn
  366 | *   |         if (intendedShares + TOLERANCE_CONSTANT < totalRequestedShares) {
  367 | *   |             revert INVALID_REDEEM_FILL();
  368 |     |         }
  369 |     | 
  370 | *   |         if (intendedShares > totalRequestedShares + TOLERANCE_CONSTANT) {
  371 |     |             revert INVALID_REDEEM_FILL();
  372 |     |         }
  373 |     | 
  374 | *   |         uint256 processedShares;
  375 | *   |         for (uint256 i; i < hooksLength; ++i) {
  376 | *   |             address hook = args.hooks[i];
  377 | *   |             uint256 amountSharesSpent = _processSingleFulfillHookExecution(
  378 |     |                 hook,
  379 | *   |                 args.hookCalldata[i],
  380 | *   |                 args.expectedAssetsOrSharesOut[i],
  381 | *   |                 currentPPS
  382 |     |             );
  383 | *   |             processedShares += amountSharesSpent;
  384 |     |         }
  385 |     | 
  386 |     |         // Post-condition: processed shares must match intended shares
  387 | *   |         if (processedShares != intendedShares) revert INVALID_REDEEM_FILL();
  388 |     | 
  389 | *   |         _processRedeemFulfillments(
  390 | *   |             args.controllers,
  391 | *   |             controllersLength,
  392 | *   |             processedShares,
  393 | *   |             currentPPS
  394 |     |         );
  395 |     | 
  396 | *   |         ISuperVault(_vault).burnShares(processedShares);
  397 |     | 
  398 | *   |         emit RedeemRequestsFulfilled(
  399 | *   |             args.hooks,
  400 | *   |             args.controllers,
  401 | *   |             processedShares,
  402 | *   |             currentPPS
  403 |     |         );
  404 |     |     }
  405 |     | 
  406 |     |     /*//////////////////////////////////////////////////////////////
  407 |     |                         YIELD SOURCE MANAGEMENT
  408 |     |     //////////////////////////////////////////////////////////////*/
  409 |     | 
  410 |     |     // @inheritdoc ISuperVaultStrategy
  411 | *   |     function manageYieldSource(
  412 |     |         address source,
  413 |     |         address oracle,
  414 |     |         uint8 actionType
  415 |     |     ) external {
  416 | *   |         _isPrimaryManager(msg.sender);
  417 | *   |         _manageYieldSource(source, oracle, actionType);
  418 |     |     }
  419 |     | 
  420 |     |     // @inheritdoc ISuperVaultStrategy
  421 | *   |     function manageYieldSources(
  422 |     |         address[] calldata sources,
  423 |     |         address[] calldata oracles,
  424 |     |         uint8[] calldata actionTypes
  425 |     |     ) external {
  426 | *   |         _isPrimaryManager(msg.sender);
  427 |     | 
  428 | *   |         uint256 length = sources.length;
  429 | *   |         if (length == 0) revert ZERO_LENGTH();
  430 | *   |         if (oracles.length != length) revert INVALID_ARRAY_LENGTH();
  431 | *   |         if (actionTypes.length != length) revert INVALID_ARRAY_LENGTH();
  432 |     | 
  433 | *   |         for (uint256 i; i < length; ++i) {
  434 | *   |             _manageYieldSource(sources[i], oracles[i], actionTypes[i]);
  435 |     |         }
  436 |     |     }
  437 |     | 
  438 |     |     // @inheritdoc ISuperVaultStrategy
  439 | *   |     function proposeVaultFeeConfigUpdate(
  440 |     |         uint256 performanceFeeBps,
  441 |     |         uint256 managementFeeBps,
  442 |     |         address recipient
  443 |     |     ) external {
  444 | *   |         _isPrimaryManager(msg.sender);
  445 |     | 
  446 | *   |         if (performanceFeeBps > BPS_PRECISION)
  447 | *   |             revert INVALID_PERFORMANCE_FEE_BPS();
  448 | *   |         if (managementFeeBps > BPS_PRECISION)
  449 | *   |             revert INVALID_PERFORMANCE_FEE_BPS();
  450 | *   |         if (recipient == address(0)) revert ZERO_ADDRESS();
  451 | *   |         proposedFeeConfig = FeeConfig({
  452 |     |             performanceFeeBps: performanceFeeBps,
  453 |     |             managementFeeBps: managementFeeBps,
  454 |     |             recipient: recipient
  455 |     |         });
  456 | *   |         feeConfigEffectiveTime = block.timestamp + ONE_WEEK;
  457 | *   |         emit VaultFeeConfigProposed(
  458 |     |             performanceFeeBps,
  459 |     |             managementFeeBps,
  460 |     |             recipient,
  461 |     |             feeConfigEffectiveTime
  462 |     |         );
  463 |     |     }
  464 |     | 
  465 |     |     // @inheritdoc ISuperVaultStrategy
  466 | *   |     function executeVaultFeeConfigUpdate() external {
  467 | *   |         if (block.timestamp < feeConfigEffectiveTime)
  468 | *   |             revert INVALID_TIMESTAMP();
  469 | *   |         if (proposedFeeConfig.recipient == address(0)) revert ZERO_ADDRESS();
  470 | *   |         feeConfig = proposedFeeConfig;
  471 | *   |         delete proposedFeeConfig;
  472 | *   |         feeConfigEffectiveTime = 0;
  473 | *   |         emit VaultFeeConfigUpdated(
  474 |     |             feeConfig.performanceFeeBps,
  475 |     |             feeConfig.managementFeeBps,
  476 |     |             feeConfig.recipient
  477 |     |         );
  478 |     |     }
  479 |     | 
  480 |     |     // @inheritdoc ISuperVaultStrategy
  481 | *   |     function updateMaxPPSSlippage(uint256 maxSlippageBps) external {
  482 | *   |         _isPrimaryManager(msg.sender);
  483 | *   |         if (maxSlippageBps > BPS_PRECISION) revert INVALID_MAX_SLIPPAGE_BPS();
  484 | *   |         _maxPPSSlippage = maxSlippageBps;
  485 | *   |         emit MaxPPSSlippageUpdated(maxSlippageBps);
  486 |     |     }
  487 |     | 
  488 |     |     // @inheritdoc ISuperVaultStrategy
  489 | *   |     function manageEmergencyWithdraw(
  490 |     |         uint8 action,
  491 |     |         address recipient,
  492 |     |         uint256 amount
  493 |     |     ) external {
  494 | *   |         if (action == 1) {
  495 | *   |             _proposeEmergencyWithdraw();
  496 | *   |         } else if (action == 2) {
  497 | *   |             _executeEmergencyWithdrawActivation();
  498 | *   |         } else if (action == 3) {
  499 | *   |             _performEmergencyWithdraw(recipient, amount);
  500 | *   |         } else if (action == 4) {
  501 | *   |             _cancelEmergencyWithdrawProposal();
  502 |     |         } else {
  503 |     |             revert ACTION_TYPE_DISALLOWED();
  504 |     |         }
  505 |     |     }
  506 |     | 
  507 |     |     /*//////////////////////////////////////////////////////////////
  508 |     |                         ACCOUNTING MANAGEMENT
  509 |     |     //////////////////////////////////////////////////////////////*/
  510 |     |     /// @inheritdoc ISuperVaultStrategy
  511 | *   |     function moveAccumulatorOnTransfer(
  512 |     |         address from,
  513 |     |         address to,
  514 |     |         uint256 shares
  515 |     |     ) external {
  516 | *   |         _requireVault();
  517 | *   |         if (shares == 0) return;
  518 |     | 
  519 | *   |         SuperVaultState storage fromState = superVaultState[from];
  520 | *   |         SuperVaultState storage toState = superVaultState[to];
  521 |     | 
  522 |     |         // Only move accumulator proportional to what's available
  523 |     |         // (accumulator shares may be less than ERC20 shares due to pending redeems)
  524 |     |         // see test_Fix1_AuditAttackScenarioFails
  525 | *   |         uint256 availableAccumulatorShares = fromState.accumulatorShares;
  526 | *   |         if (availableAccumulatorShares == 0) return; // No accumulator to move
  527 |     | 
  528 | *   |         uint256 sharesToMove = shares > availableAccumulatorShares
  529 | *   |             ? availableAccumulatorShares
  530 | *   |             : shares;
  531 |     | 
  532 |     |         // Pro-rata move of cost basis (NO PPS here; preserves fee correctness)
  533 | *   |         uint256 movedCostBasis = sharesToMove == availableAccumulatorShares
  534 | *   |             ? fromState.accumulatorCostBasis
  535 | *   |             : Math.mulDiv(
  536 | *   |                 sharesToMove,
  537 | *   |                 fromState.accumulatorCostBasis,
  538 | *   |                 availableAccumulatorShares,
  539 | *   |                 Math.Rounding.Floor
  540 |     |             ); /// @audit is there a value st when transfered transfers minimal shares and maximum cost basis
  541 |     | 
  542 | *   |         fromState.accumulatorShares -= sharesToMove;
  543 | *   |         fromState.accumulatorCostBasis -= movedCostBasis;
  544 |     | 
  545 | *   |         toState.accumulatorShares += sharesToMove;
  546 | *   |         toState.accumulatorCostBasis += movedCostBasis;
  547 |     | 
  548 |     |         // Never touch: pendingRedeemRequest, averageRequestPPS, maxWithdraw, averageWithdrawPrice
  549 |     |     }
  550 |     | 
  551 |     |     /*//////////////////////////////////////////////////////////////
  552 |     |                             VIEW FUNCTIONS
  553 |     |     //////////////////////////////////////////////////////////////*/
  554 |     | 
  555 |     |     // @inheritdoc ISuperVaultStrategy
  556 |     |     function getVaultInfo()
  557 |     |         external
  558 |     |         view
  559 |     |         returns (address vault, address asset, uint8 vaultDecimals)
  560 |     |     {
  561 |     |         vault = _vault;
  562 |     |         asset = address(_asset);
  563 |     |         vaultDecimals = _vaultDecimals;
  564 |     |     }
  565 |     | 
  566 |     |     // @inheritdoc ISuperVaultStrategy
  567 | *   |     function getConfigInfo()
  568 |     |         external
  569 |     |         view
  570 | *   |         returns (FeeConfig memory feeConfig_)
  571 |     |     {
  572 | *   |         feeConfig_ = feeConfig;
  573 |     |     }
  574 |     | 
  575 |     |     // @inheritdoc ISuperVaultStrategy
  576 | *   |     function getStoredPPS() public view returns (uint256) {
  577 | *   |         return _getSuperVaultAggregator().getPPS(address(this));
  578 |     |     }
  579 |     | 
  580 |     |     // @inheritdoc ISuperVaultStrategy
  581 | *   |     function getSuperVaultState(
  582 |     |         address controller
  583 | *   |     ) external view returns (SuperVaultState memory state) {
  584 | *   |         return superVaultState[controller];
  585 |     |     }
  586 |     | 
  587 |     |     // @inheritdoc ISuperVaultStrategy
  588 |     |     function getYieldSource(
  589 |     |         address source
  590 |     |     ) external view returns (YieldSource memory) {
  591 |     |         return YieldSource({oracle: yieldSources[source]});
  592 |     |     }
  593 |     | 
  594 |     |     // @inheritdoc ISuperVaultStrategy
  595 |     |     function getYieldSourcesList()
  596 |     |         external
  597 |     |         view
  598 |     |         returns (YieldSourceInfo[] memory)
  599 |     |     {
  600 |     |         uint256 length = yieldSourcesList.length();
  601 |     |         YieldSourceInfo[] memory sourcesInfo = new YieldSourceInfo[](length);
  602 |     | 
  603 |     |         for (uint256 i; i < length; ++i) {
  604 |     |             address sourceAddress = yieldSourcesList.at(i);
  605 |     |             address oracle = yieldSources[sourceAddress];
  606 |     | 
  607 |     |             sourcesInfo[i] = YieldSourceInfo({
  608 |     |                 sourceAddress: sourceAddress,
  609 |     |                 oracle: oracle
  610 |     |             });
  611 |     |         }
  612 |     | 
  613 |     |         return sourcesInfo;
  614 |     |     }
  615 |     | 
  616 |     |     // @inheritdoc ISuperVaultStrategy
  617 |     |     function getYieldSources() external view returns (address[] memory) {
  618 |     |         return yieldSourcesList.values();
  619 |     |     }
  620 |     | 
  621 |     |     // @inheritdoc ISuperVaultStrategy
  622 |     |     function getYieldSourcesCount() external view returns (uint256) {
  623 |     |         return yieldSourcesList.length();
  624 |     |     }
  625 |     | 
  626 |     |     // @inheritdoc ISuperVaultStrategy
  627 |     |     function containsYieldSource(address source) external view returns (bool) {
  628 |     |         return yieldSourcesList.contains(source);
  629 |     |     }
  630 |     | 
  631 |     |     // @inheritdoc ISuperVaultStrategy
  632 | *   |     function pendingRedeemRequest(
  633 |     |         address controller
  634 | *   |     ) external view returns (uint256 pendingShares) {
  635 | *   |         return superVaultState[controller].pendingRedeemRequest;
  636 |     |     }
  637 |     | 
  638 |     |     // @inheritdoc ISuperVaultStrategy
  639 | *   |     function claimableWithdraw(
  640 |     |         address controller
  641 | *   |     ) external view returns (uint256 claimableAssets) {
  642 | *   |         return superVaultState[controller].maxWithdraw;
  643 |     |     }
  644 |     | 
  645 |     |     // @inheritdoc ISuperVaultStrategy
  646 | *   |     function getAverageWithdrawPrice(
  647 |     |         address controller
  648 | *   |     ) external view returns (uint256 averageWithdrawPrice) {
  649 | *   |         return superVaultState[controller].averageWithdrawPrice;
  650 |     |     }
  651 |     | 
  652 |     |     // @inheritdoc ISuperVaultStrategy
  653 |     |     function previewPerformanceFee(
  654 |     |         address controller,
  655 |     |         uint256 sharesToRedeem
  656 |     |     )
  657 |     |         external
  658 |     |         view
  659 |     |         returns (uint256 totalFee, uint256 superformFee, uint256 recipientFee)
  660 |     |     {
  661 |     |         if (sharesToRedeem == 0) return (0, 0, 0);
  662 |     | 
  663 |     |         // Get controller's state
  664 |     |         SuperVaultState storage state = superVaultState[controller];
  665 |     | 
  666 |     |         // Check if controller has enough shares
  667 |     |         if (sharesToRedeem > state.accumulatorShares) return (0, 0, 0);
  668 |     | 
  669 |     |         // Get the current price per share
  670 |     |         uint256 currentPPS = getStoredPPS();
  671 |     | 
  672 |     |         // Calculate historical assets (cost basis)
  673 |     |         uint256 historicalAssets = 0;
  674 |     |         if (state.accumulatorShares > 0) {
  675 |     |             historicalAssets = sharesToRedeem.mulDiv(
  676 |     |                 state.accumulatorCostBasis,
  677 |     |                 state.accumulatorShares,
  678 |     |                 Math.Rounding.Floor
  679 |     |             );
  680 |     |         }
  681 |     | 
  682 |     |         // Calculate current value of shares in asset terms
  683 |     |         uint256 currentAssetsWithFees = sharesToRedeem.mulDiv(
  684 |     |             currentPPS,
  685 |     |             PRECISION,
  686 |     |             Math.Rounding.Floor
  687 |     |         );
  688 |     | 
  689 |     |         // Calculate fee (if any) using same logic as _calculateAndTransferFee
  690 |     |         if (currentAssetsWithFees > historicalAssets) {
  691 |     |             uint256 profit = currentAssetsWithFees - historicalAssets;
  692 |     |             uint256 performanceFeeBps = feeConfig.performanceFeeBps;
  693 |     |             totalFee = profit.mulDiv(
  694 |     |                 performanceFeeBps,
  695 |     |                 BPS_PRECISION,
  696 |     |                 Math.Rounding.Floor
  697 |     |             );
  698 |     | 
  699 |     |             if (totalFee > 0) {
  700 |     |                 // Calculate Superform's portion of the fee using revenueShare from SuperGovernor
  701 |     |                 superformFee = totalFee.mulDiv(
  702 |     |                     superGovernor.getFee(FeeType.SUPER_VAULT_PERFORMANCE_FEE),
  703 |     |                     BPS_PRECISION,
  704 |     |                     Math.Rounding.Floor
  705 |     |                 );
  706 |     |                 recipientFee = totalFee - superformFee;
  707 |     |             }
  708 |     |         }
  709 |     | 
  710 |     |         return (totalFee, superformFee, recipientFee);
  711 |     |     }
  712 |     | 
  713 |     |     /*//////////////////////////////////////////////////////////////
  714 |     |                         INTERNAL FUNCTIONS
  715 |     |     //////////////////////////////////////////////////////////////*/
  716 |     | 
  717 |     |     /// @notice Process a single hook execution
  718 |     |     /// @param hook Hook address
  719 |     |     /// @param prevHook Previous hook address
  720 |     |     /// @param hookCalldata Hook calldata
  721 |     |     /// @param expectedAssetsOrSharesOut Expected assets or shares output
  722 |     |     /// @return processedHook Processed hook address
  723 | *   |     function _processSingleHookExecution(
  724 |     |         address hook,
  725 |     |         address prevHook,
  726 |     |         bytes memory hookCalldata,
  727 |     |         uint256 expectedAssetsOrSharesOut
  728 |     |     ) internal returns (address) {
  729 |     |         ExecutionVars memory vars;
  730 | *   |         vars.hookContract = ISuperHook(hook);
  731 |     | 
  732 | *   |         vars.targetedYieldSource = HookDataDecoder.extractYieldSource(
  733 | *   |             hookCalldata
  734 |     |         );
  735 | *   |         if (yieldSources[vars.targetedYieldSource] == address(0))
  736 | *   |             revert YIELD_SOURCE_NOT_FOUND();
  737 |     | 
  738 | *   |         bool usePrevHookAmount = _decodeHookUsePrevHookAmount(
  739 | *   |             hook,
  740 | *   |             hookCalldata
  741 |     |         );
  742 | *   |         if (usePrevHookAmount && prevHook != address(0)) {
  743 |     |             vars.outAmount = _getPreviousHookOutAmount(prevHook);
  744 |     |             if (expectedAssetsOrSharesOut == 0) revert ZERO_EXPECTED_VALUE();
  745 |     |             uint256 minExpectedPrevOut = expectedAssetsOrSharesOut *
  746 |     |                 (BPS_PRECISION - _getSlippageTolerance());
  747 |     |             if (vars.outAmount * BPS_PRECISION < minExpectedPrevOut) {
  748 |     |                 revert MINIMUM_PREVIOUS_HOOK_OUT_AMOUNT_NOT_MET();
  749 |     |             }
  750 |     |         }
  751 |     | 
  752 | *   |         ISuperHook(address(vars.hookContract)).setExecutionContext(
  753 | *   |             address(this)
  754 |     |         );
  755 | *   |         vars.executions = vars.hookContract.build(
  756 | *   |             prevHook,
  757 | *   |             address(this),
  758 | *   |             hookCalldata
  759 |     |         );
  760 | *   |         for (uint256 j; j < vars.executions.length; ++j) {
  761 | *   |             (vars.success, ) = vars.executions[j].target.call{
  762 | *   |                 value: vars.executions[j].value
  763 | *   |             }(vars.executions[j].callData);
  764 | *   |             if (!vars.success) revert OPERATION_FAILED();
  765 |     |         }
  766 | *   |         ISuperHook(address(vars.hookContract)).resetExecutionState(
  767 | *   |             address(this)
  768 |     |         );
  769 |     | 
  770 | *   |         uint256 actualOutput = ISuperHookResult(hook).getOutAmount(
  771 | *   |             address(this)
  772 |     |         );
  773 | *   |         if (actualOutput == 0) revert ZERO_OUTPUT_AMOUNT();
  774 |     | 
  775 | *   |         uint256 minExpectedOut = (expectedAssetsOrSharesOut *
  776 | *   |             (BPS_PRECISION - _getSlippageTolerance())) / BPS_PRECISION;
  777 | *   |         if (actualOutput < minExpectedOut) {
  778 |     |             revert MINIMUM_OUTPUT_AMOUNT_ASSETS_NOT_MET();
  779 |     |         }
  780 |     | 
  781 | *   |         emit HookExecuted(
  782 | *   |             hook,
  783 | *   |             prevHook,
  784 | *   |             vars.targetedYieldSource,
  785 | *   |             usePrevHookAmount,
  786 | *   |             hookCalldata
  787 |     |         );
  788 |     | 
  789 | *   |         return hook;
  790 |     |     }
  791 |     | 
  792 |     |     /// @notice Process a single hook fulfillment execution
  793 |     |     /// @param hook Hook address
  794 |     |     /// @param hookCalldata Hook calldata
  795 |     |     /// @param expectedAssetOutput Expected asset output
  796 |     |     /// @param currentPPS Current price per share
  797 |     |     /// @return processedShares Processed shares
  798 | *   |     function _processSingleFulfillHookExecution(
  799 |     |         address hook,
  800 |     |         bytes memory hookCalldata,
  801 |     |         uint256 expectedAssetOutput,
  802 |     |         uint256 currentPPS
  803 |     |     ) internal returns (uint256) {
  804 |     |         OutflowExecutionVars memory vars;
  805 | *   |         vars.hookContract = ISuperHook(hook);
  806 | *   |         vars.hookType = ISuperHookResult(hook).hookType();
  807 | *   |         if (vars.hookType != ISuperHook.HookType.OUTFLOW)
  808 |     |             revert INVALID_HOOK_TYPE();
  809 |     | 
  810 | *   |         vars.targetedYieldSource = HookDataDecoder.extractYieldSource(
  811 | *   |             hookCalldata
  812 |     |         );
  813 | *   |         if (yieldSources[vars.targetedYieldSource] == address(0))
  814 | *   |             revert YIELD_SOURCE_NOT_FOUND();
  815 |     | 
  816 |     |         // we must always encode supervault shares when fulfilling redemptions
  817 | *   |         vars.superVaultShares = ISuperHookInflowOutflow(hook).decodeAmount(
  818 | *   |             hookCalldata
  819 |     |         );
  820 |     | 
  821 |     |         // Calculate underlying shares and update hook calldata
  822 | *   |         vars.amountOfAssets = vars.superVaultShares.mulDiv(
  823 | *   |             currentPPS,
  824 | *   |             PRECISION,
  825 |     |             Math.Rounding.Floor
  826 |     |         );
  827 | *   |         vars.svAsset = address(_asset);
  828 | *   |         vars.amountConvertedToUnderlyingShares = IYieldSourceOracle(
  829 | *   |             yieldSources[vars.targetedYieldSource]
  830 |     |         ).getShareOutput(
  831 | *   |                 vars.targetedYieldSource,
  832 | *   |                 vars.svAsset,
  833 | *   |                 vars.amountOfAssets
  834 |     |             );
  835 | *   |         hookCalldata = ISuperHookOutflow(hook).replaceCalldataAmount(
  836 | *   |             hookCalldata,
  837 |     |             vars.amountConvertedToUnderlyingShares
  838 |     |         );
  839 |     | 
  840 | *   |         vars.balanceAssetBefore = _getTokenBalance(vars.svAsset, address(this));
  841 |     | 
  842 | *   |         ISuperHook(address(vars.hookContract)).setExecutionContext(
  843 | *   |             address(this)
  844 |     |         );
  845 |     | 
  846 | *   |         vars.executions = vars.hookContract.build(
  847 | *   |             address(0),
  848 | *   |             address(this),
  849 | *   |             hookCalldata
  850 |     |         );
  851 | *   |         for (uint256 j; j < vars.executions.length; ++j) {
  852 | *   |             (vars.success, ) = vars.executions[j].target.call(
  853 | *   |                 vars.executions[j].callData
  854 |     |             );
  855 | *   |             if (!vars.success) revert OPERATION_FAILED();
  856 |     |         }
  857 | *   |         ISuperHook(address(vars.hookContract)).resetExecutionState(
  858 | *   |             address(this)
  859 |     |         );
  860 |     | 
  861 | *   |         vars.outAmount =
  862 | *   |             _getTokenBalance(vars.svAsset, address(this)) -
  863 | *   |             vars.balanceAssetBefore;
  864 |     | 
  865 | *   |         if (vars.outAmount == 0) revert ZERO_OUTPUT_AMOUNT();
  866 | *   |         if (
  867 | *   |             vars.outAmount * BPS_PRECISION <
  868 | *   |             expectedAssetOutput * (BPS_PRECISION - _getSlippageTolerance())
  869 |     |         ) {
  870 | *   |             revert MINIMUM_OUTPUT_AMOUNT_ASSETS_NOT_MET();
  871 |     |         }
  872 | *   |         emit FulfillHookExecuted(hook, vars.targetedYieldSource, hookCalldata);
  873 |     | 
  874 | *   |         return vars.superVaultShares;
  875 |     |     }
  876 |     | 
  877 |     |     /// @notice Process redeem fulfillments for multiple controllers
  878 |     |     /// @param controllers Array of controller addresses
  879 |     |     /// @param controllersLength Length of controllers array
  880 |     |     /// @param processedShares Total shares processed
  881 |     |     /// @param currentPPS Current price per share
  882 | *   |     function _processRedeemFulfillments(
  883 |     |         address[] calldata controllers,
  884 |     |         uint256 controllersLength,
  885 |     |         uint256 processedShares,
  886 |     |         uint256 currentPPS
  887 |     |     ) internal {
  888 | *   |         for (uint256 i; i < controllersLength; ++i) {
  889 | *   |             SuperVaultState storage state = superVaultState[controllers[i]];
  890 |     | 
  891 | *   |             uint256 crtControllerRequestedAmount = state.pendingRedeemRequest;
  892 |     |             // Check for PPS slippage if there's a recorded request PPS and max slippage is set
  893 | *   |             if (state.averageRequestPPS > 0 && _maxPPSSlippage > 0) {
  894 | *   |                 uint256 averageRequestPPS = state.averageRequestPPS;
  895 |     |                 // Calculate the percentage decrease from request PPS to current PPS
  896 | *   |                 if (currentPPS < averageRequestPPS) {
  897 |     |                     uint256 decrease = (
  898 |     |                         (averageRequestPPS - currentPPS).mulDiv(
  899 |     |                             BPS_PRECISION,
  900 |     |                             averageRequestPPS,
  901 |     |                             Math.Rounding.Floor
  902 |     |                         )
  903 |     |                     );
  904 |     |                     // If decrease exceeds maximum allowed slippage, revert
  905 |     |                     if (decrease > _maxPPSSlippage) revert SLIPPAGE_EXCEEDED();
  906 |     |                 }
  907 |     |             }
  908 |     | 
  909 | *   |             uint256 currentAssets = _calculateHistoricalAssetsAndProcessFees(
  910 | *   |                 state,
  911 | *   |                 crtControllerRequestedAmount,
  912 | *   |                 currentPPS
  913 |     |             );
  914 |     | 
  915 |     |             // Update user state, no partial redeems allowed
  916 | *   |             state.pendingRedeemRequest = 0;
  917 | *   |             state.maxWithdraw += currentAssets;
  918 | *   |             state.averageRequestPPS = 0; // Reset PPS value after fulfillment
  919 |     | 
  920 |     |             // Call vault callback
  921 | *   |             _onRedeemClaimable(
  922 | *   |                 controllers[i],
  923 | *   |                 currentAssets,
  924 | *   |                 crtControllerRequestedAmount,
  925 | *   |                 state.averageWithdrawPrice,
  926 | *   |                 state.accumulatorShares,
  927 | *   |                 state.accumulatorCostBasis
  928 |     |             );
  929 |     |         }
  930 |     |     }
  931 |     | 
  932 |     |     /// @notice Calculate historical assets and process fees
  933 |     |     /// @param state User's vault state
  934 |     |     /// @param requestedShares Shares being redeemed
  935 |     |     /// @param currentPricePerShare Current price per share
  936 | *   |     function _calculateHistoricalAssetsAndProcessFees(
  937 |     |         SuperVaultState storage state,
  938 |     |         uint256 requestedShares,
  939 |     |         uint256 currentPricePerShare
  940 | *   |     ) private returns (uint256 currentAssets) {
  941 |     |         // Calculate cost basis based on requested shares
  942 | *   |         uint256 historicalAssets = _calculateCostBasis(state, requestedShares);
  943 | *   |         uint256 currentAssetsWithFees;
  944 |     |         // Process fees and get final assets
  945 | *   |         (currentAssetsWithFees, currentAssets) = _processFees(
  946 | *   |             requestedShares,
  947 | *   |             currentPricePerShare,
  948 | *   |             historicalAssets
  949 |     |         );
  950 |     | 
  951 |     |         // Update average withdraw price if needed
  952 | *   |         if (requestedShares > 0) {
  953 | *   |             _updateAverageWithdrawPrice(
  954 | *   |                 state,
  955 | *   |                 requestedShares,
  956 | *   |                 currentAssetsWithFees
  957 |     |             );
  958 |     |         }
  959 |     | 
  960 | *   |         return currentAssets;
  961 |     |     }
  962 |     | 
  963 |     |     /// @notice Calculate cost basis for requested shares using weighted average approach
  964 |     |     /// @param state User's vault state
  965 |     |     /// @param requestedShares Shares being redeemed
  966 | *   |     function _calculateCostBasis(
  967 |     |         SuperVaultState storage state,
  968 |     |         uint256 requestedShares
  969 | *   |     ) private returns (uint256 costBasis) {
  970 | *   |         if (requestedShares > state.accumulatorShares)
  971 |     |             revert INSUFFICIENT_SHARES();
  972 |     | 
  973 |     |         // Calculate cost basis proportionally
  974 | *   |         costBasis = requestedShares.mulDiv(
  975 | *   |             state.accumulatorCostBasis,
  976 | *   |             state.accumulatorShares,
  977 | *   |             Math.Rounding.Floor
  978 |     |         );
  979 |     | 
  980 |     |         // Update user's accumulator state
  981 | *   |         state.accumulatorShares -= requestedShares;
  982 | *   |         state.accumulatorCostBasis -= costBasis;
  983 |     | 
  984 |     |         return costBasis;
  985 |     |     }
  986 |     | 
  987 |     |     // --- Fee Processing ---
  988 |     |     /// @notice Calculate and transfer fees based on profit
  989 |     |     /// @param requestedShares Shares being redeemed
  990 |     |     /// @param currentPricePerShare Current price per share
  991 |     |     /// @param historicalAssets Historical value of shares in assets
  992 |     |     /// @return currentAssetsWithFees Current value of shares in assets (not net of fees)
  993 |     |     /// @return currentAssets Current assets after fee deduction
  994 | *   |     function _processFees(
  995 |     |         uint256 requestedShares,
  996 |     |         uint256 currentPricePerShare,
  997 |     |         uint256 historicalAssets
  998 | *   |     ) private returns (uint256 currentAssetsWithFees, uint256 currentAssets) {
  999 |     |         // Calculate current value of the shares at current price
 1000 | *   |         currentAssetsWithFees = requestedShares.mulDiv(
 1001 | *   |             currentPricePerShare,
 1002 | *   |             PRECISION,
 1003 |     |             Math.Rounding.Floor
 1004 |     |         );
 1005 |     | 
 1006 |     |         // Apply fees only on profit
 1007 | *   |         currentAssets = _calculateAndTransferFee(
 1008 | *   |             currentAssetsWithFees,
 1009 | *   |             historicalAssets
 1010 |     |         );
 1011 |     | 
 1012 |     |         // Ensure we don't exceed available balance
 1013 | *   |         uint256 balanceOfStrategy = _getTokenBalance(
 1014 | *   |             address(_asset),
 1015 | *   |             address(this)
 1016 |     |         );
 1017 | *   |         currentAssets = currentAssets > balanceOfStrategy
 1018 | *   |             ? balanceOfStrategy
 1019 | *   |             : currentAssets;
 1020 |     | 
 1021 | *   |         return (currentAssetsWithFees, currentAssets);
 1022 |     |     }
 1023 |     | 
 1024 |     |     /// @notice Calculate fee on profit and transfer to recipient
 1025 |     |     /// @param currentAssetsWithFees Current value of shares in assets (not net of fees)
 1026 |     |     /// @param historicalAssets Historical value of shares in assets
 1027 |     |     /// @return currentAssets Current assets after fee deduction
 1028 | *   |     function _calculateAndTransferFee(
 1029 |     |         uint256 currentAssetsWithFees,
 1030 |     |         uint256 historicalAssets
 1031 |     |     ) private returns (uint256 currentAssets) {
 1032 | *   |         currentAssets = currentAssetsWithFees;
 1033 | *   |         if (currentAssetsWithFees > historicalAssets) {
 1034 | *   |             uint256 profit = currentAssetsWithFees - historicalAssets;
 1035 | *   |             uint256 performanceFeeBps = feeConfig.performanceFeeBps;
 1036 | *   |             uint256 totalFee = profit.mulDiv(
 1037 |     |                 performanceFeeBps,
 1038 |     |                 BPS_PRECISION,
 1039 |     |                 Math.Rounding.Floor
 1040 |     |             );
 1041 | *   |             if (totalFee > 0) {
 1042 |     |                 // Calculate Superform's portion of the fee using revenueShare from SuperGovernor
 1043 | *   |                 uint256 superformFee = totalFee.mulDiv(
 1044 | *   |                     superGovernor.getFee(FeeType.SUPER_VAULT_PERFORMANCE_FEE),
 1045 |     |                     BPS_PRECISION,
 1046 | *   |                     Math.Rounding.Floor
 1047 |     |                 );
 1048 | *   |                 uint256 recipientFee = totalFee - superformFee;
 1049 |     | 
 1050 |     |                 // Transfer fees
 1051 | *   |                 if (superformFee > 0) {
 1052 |     |                     // Get treasury address from SuperGovernor
 1053 | *   |                     address treasury = superGovernor.getAddress(
 1054 | *   |                         superGovernor.TREASURY()
 1055 |     |                     );
 1056 | *   |                     _safeTokenTransfer(address(_asset), treasury, superformFee);
 1057 | *   |                     emit FeePaid(treasury, superformFee, performanceFeeBps);
 1058 |     |                 }
 1059 |     | 
 1060 | *   |                 if (recipientFee > 0) {
 1061 | *   |                     address recipient = feeConfig.recipient;
 1062 | *   |                     if (recipient == address(0)) revert ZERO_ADDRESS();
 1063 | *   |                     _safeTokenTransfer(
 1064 | *   |                         address(_asset),
 1065 | *   |                         recipient,
 1066 | *   |                         recipientFee
 1067 |     |                     );
 1068 | *   |                     emit FeePaid(recipient, recipientFee, performanceFeeBps);
 1069 |     |                 }
 1070 |     | 
 1071 | *   |                 currentAssets -= totalFee;
 1072 |     |             }
 1073 |     |         }
 1074 |     |         return currentAssets;
 1075 |     |     }
 1076 |     | 
 1077 |     |     /// @notice Internal function to update the average withdraw price
 1078 |     |     /// @param state Storage reference to the vault state
 1079 |     |     /// @param requestedShares Number of shares requested
 1080 |     |     /// @param currentAssetsWithFees Current assets with fees
 1081 | *   |     function _updateAverageWithdrawPrice(
 1082 |     |         SuperVaultState storage state,
 1083 |     |         uint256 requestedShares,
 1084 |     |         uint256 currentAssetsWithFees
 1085 | *   |     ) private {
 1086 | *   |         uint256 existingShares;
 1087 | *   |         uint256 existingAssets;
 1088 |     | 
 1089 | *   |         if (state.maxWithdraw > 0 && state.averageWithdrawPrice > 0) {
 1090 | *   |             existingShares = state.maxWithdraw.mulDiv(
 1091 | *   |                 PRECISION,
 1092 | *   |                 state.averageWithdrawPrice,
 1093 | *   |                 Math.Rounding.Floor
 1094 |     |             );
 1095 | *   |             existingAssets = state.maxWithdraw;
 1096 |     |         }
 1097 |     | 
 1098 | *   |         uint256 newTotalShares = existingShares + requestedShares;
 1099 | *   |         uint256 newTotalAssets = existingAssets + currentAssetsWithFees;
 1100 |     | 
 1101 | *   |         if (newTotalShares > 0) {
 1102 | *   |             state.averageWithdrawPrice = newTotalAssets.mulDiv(
 1103 | *   |                 PRECISION,
 1104 | *   |                 newTotalShares,
 1105 |     |                 Math.Rounding.Floor
 1106 |     |             );
 1107 |     |         }
 1108 |     |     }
 1109 |     | 
 1110 |     |     /// @notice Internal function to get the SuperVaultAggregator
 1111 |     |     /// @return The SuperVaultAggregator
 1112 | *   |     function _getSuperVaultAggregator()
 1113 |     |         internal
 1114 |     |         view
 1115 | *   |         returns (ISuperVaultAggregator)
 1116 |     |     {
 1117 | *   |         address aggregatorAddress = superGovernor.getAddress(
 1118 | *   |             superGovernor.SUPER_VAULT_AGGREGATOR()
 1119 |     |         );
 1120 |     | 
 1121 |     |         return ISuperVaultAggregator(aggregatorAddress);
 1122 |     |     }
 1123 |     | 
 1124 |     |     /// @notice Internal function to check if a manager is authorized
 1125 |     |     /// @param manager_ The manager to check
 1126 | *   |     function _isManager(address manager_) internal view {
 1127 | *   |         if (!_getSuperVaultAggregator().isAnyManager(manager_, address(this))) {
 1128 | *   |             revert MANAGER_NOT_AUTHORIZED();
 1129 |     |         }
 1130 |     |     }
 1131 |     | 
 1132 |     |     /// @notice Internal function to check if a manager is the primary manager
 1133 |     |     /// @param manager_ The manager to check
 1134 | *   |     function _isPrimaryManager(address manager_) internal view {
 1135 |     |         if (
 1136 | *   |             !_getSuperVaultAggregator().isMainManager(manager_, address(this))
 1137 |     |         ) {
 1138 |     |             revert MANAGER_NOT_AUTHORIZED();
 1139 |     |         }
 1140 |     |     }
 1141 |     | 
 1142 |     |     /// @notice Internal function to manage a yield source
 1143 |     |     /// @param source Address of the yield source
 1144 |     |     /// @param oracle Address of the oracle
 1145 |     |     /// @param actionType Type of action: 0=Add, 1=UpdateOracle, 2=Remove
 1146 | *   |     function _manageYieldSource(
 1147 |     |         address source,
 1148 |     |         address oracle,
 1149 |     |         uint8 actionType
 1150 |     |     ) internal {
 1151 | *   |         if (actionType == 0) {
 1152 | *   |             _addYieldSource(source, oracle);
 1153 | *   |         } else if (actionType == 1) {
 1154 | *   |             _updateYieldSourceOracle(source, oracle);
 1155 | *   |         } else if (actionType == 2) {
 1156 | *   |             _removeYieldSource(source);
 1157 |     |         } else {
 1158 |     |             revert ACTION_TYPE_DISALLOWED();
 1159 |     |         }
 1160 |     |     }
 1161 |     | 
 1162 |     |     /// @notice Internal function to add a yield source
 1163 |     |     /// @param source Address of the yield source
 1164 |     |     /// @param oracle Address of the oracle
 1165 | *   |     function _addYieldSource(address source, address oracle) internal {
 1166 | *   |         if (source == address(0) || oracle == address(0)) revert ZERO_ADDRESS();
 1167 | *   |         if (yieldSources[source] != address(0))
 1168 | *   |             revert YIELD_SOURCE_ALREADY_EXISTS();
 1169 | *   |         yieldSources[source] = oracle;
 1170 | *   |         if (!yieldSourcesList.add(source)) revert YIELD_SOURCE_ALREADY_EXISTS();
 1171 |     | 
 1172 | *   |         emit YieldSourceAdded(source, oracle);
 1173 |     |     }
 1174 |     | 
 1175 |     |     /// @notice Internal function to update a yield source's oracle
 1176 |     |     /// @param source Address of the yield source
 1177 |     |     /// @param oracle Address of the oracle
 1178 | *   |     function _updateYieldSourceOracle(address source, address oracle) internal {
 1179 | *   |         if (oracle == address(0)) revert ZERO_ADDRESS();
 1180 | *   |         address oldOracle = yieldSources[source];
 1181 | *   |         if (oldOracle == address(0)) revert YIELD_SOURCE_NOT_FOUND();
 1182 | *   |         yieldSources[source] = oracle;
 1183 |     | 
 1184 | *   |         emit YieldSourceOracleUpdated(source, oldOracle, oracle);
 1185 |     |     }
 1186 |     | 
 1187 |     |     /// @notice Internal function to remove a yield source
 1188 |     |     /// @param source Address of the yield source
 1189 | *   |     function _removeYieldSource(address source) internal {
 1190 | *   |         if (yieldSources[source] == address(0)) revert YIELD_SOURCE_NOT_FOUND();
 1191 |     | 
 1192 |     |         // Remove from mapping
 1193 | *   |         delete yieldSources[source];
 1194 |     | 
 1195 |     |         // Remove from EnumerableSet
 1196 | *   |         if (!yieldSourcesList.remove(source)) revert YIELD_SOURCE_NOT_FOUND();
 1197 |     | 
 1198 | *   |         emit YieldSourceRemoved(source);
 1199 |     |     }
 1200 |     | 
 1201 |     |     /// @notice Internal function to propose an emergency withdraw
 1202 | *   |     function _proposeEmergencyWithdraw() internal {
 1203 | *   |         _isPrimaryManager(msg.sender);
 1204 |     | 
 1205 | *   |         proposedEmergencyWithdrawable = true;
 1206 | *   |         emergencyWithdrawableEffectiveTime = block.timestamp + ONE_WEEK;
 1207 | *   |         emit EmergencyWithdrawableProposed(
 1208 | *   |             true,
 1209 |     |             emergencyWithdrawableEffectiveTime
 1210 |     |         );
 1211 |     |     }
 1212 |     | 
 1213 |     |     /// @notice Internal function to execute an emergency withdraw
 1214 | *   |     function _executeEmergencyWithdrawActivation() internal {
 1215 | *   |         if (emergencyWithdrawableEffectiveTime == 0) revert NO_PROPOSAL();
 1216 | *   |         if (block.timestamp < emergencyWithdrawableEffectiveTime)
 1217 | *   |             revert INVALID_TIMESTAMP();
 1218 | *   |         emergencyWithdrawable = proposedEmergencyWithdrawable;
 1219 | *   |         proposedEmergencyWithdrawable = false;
 1220 | *   |         emergencyWithdrawableEffectiveTime = 0;
 1221 | *   |         emit EmergencyWithdrawableUpdated(emergencyWithdrawable);
 1222 |     |     }
 1223 |     | 
 1224 |     |     /// @notice Internal function to cancel an emergency withdraw proposal
 1225 | *   |     function _cancelEmergencyWithdrawProposal() internal {
 1226 | *   |         _isPrimaryManager(msg.sender);
 1227 |     | 
 1228 | *   |         if (emergencyWithdrawableEffectiveTime == 0) revert NO_PROPOSAL();
 1229 | *   |         proposedEmergencyWithdrawable = false;
 1230 | *   |         emergencyWithdrawableEffectiveTime = 0;
 1231 | *   |         emit EmergencyWithdrawableProposalCanceled();
 1232 |     |     }
 1233 |     | 
 1234 |     |     /// @notice Internal function to perform an emergency withdraw
 1235 |     |     /// @param recipient Address to receive the assets
 1236 |     |     /// @param amount Amount of assets to withdraw
 1237 | *   |     function _performEmergencyWithdraw(
 1238 |     |         address recipient,
 1239 |     |         uint256 amount
 1240 |     |     ) internal {
 1241 | *   |         _isPrimaryManager(msg.sender);
 1242 |     | 
 1243 | *   |         if (!emergencyWithdrawable) revert INVALID_EMERGENCY_WITHDRAWAL();
 1244 | *   |         if (recipient == address(0)) revert ZERO_ADDRESS();
 1245 | *   |         uint256 freeAssets = _getTokenBalance(address(_asset), address(this));
 1246 | *   |         if (amount == 0 || amount > freeAssets) revert INSUFFICIENT_FUNDS();
 1247 |     |         _safeTokenTransfer(address(_asset), recipient, amount);
 1248 |     |         emit EmergencyWithdrawal(recipient, amount);
 1249 |     |     }
 1250 |     | 
 1251 |     |     /// @notice Internal function to check if a hook is a fulfill requests hook
 1252 |     |     /// @param hook Address of the hook
 1253 |     |     /// @return True if the hook is a fulfill requests hook, false otherwise
 1254 | *   |     function _isFulfillRequestsHook(address hook) private view returns (bool) {
 1255 | *   |         return superGovernor.isFulfillRequestsHookRegistered(hook);
 1256 |     |     }
 1257 |     | 
 1258 |     |     /// @notice Internal function to check if a hook is registered
 1259 |     |     /// @param hook Address of the hook
 1260 |     |     /// @return True if the hook is registered, false otherwise
 1261 | *   |     function _isRegisteredHook(address hook) private view returns (bool) {
 1262 | *   |         return superGovernor.isHookRegistered(hook);
 1263 |     |     }
 1264 |     | 
 1265 |     |     /// @notice Internal function to decode a hook's use previous hook amount
 1266 |     |     /// @param hook Address of the hook
 1267 |     |     /// @param hookCalldata Call data for the hook
 1268 |     |     /// @return True if the hook should use the previous hook amount, false otherwise
 1269 | *   |     function _decodeHookUsePrevHookAmount(
 1270 |     |         address hook,
 1271 |     |         bytes memory hookCalldata
 1272 | *   |     ) private pure returns (bool) {
 1273 | *   |         try
 1274 | *   |             ISuperHookContextAware(hook).decodeUsePrevHookAmount(hookCalldata)
 1275 |     |         returns (bool usePrevHookAmount) {
 1276 | *   |             return usePrevHookAmount;
 1277 |     |         } catch {
 1278 | *   |             return false;
 1279 |     |         }
 1280 |     |     }
 1281 |     | 
 1282 |     |     /// @notice Internal function to get the previous hook's output amount
 1283 |     |     /// @param prevHook Address of the previous hook
 1284 |     |     /// @return Output amount of the previous hook
 1285 |     |     function _getPreviousHookOutAmount(
 1286 |     |         address prevHook
 1287 |     |     ) private view returns (uint256) {
 1288 |     |         return ISuperHookResultOutflow(prevHook).getOutAmount(address(this));
 1289 |     |     }
 1290 |     | 
 1291 |     |     /// @notice Internal function to handle a redeem claimable
 1292 |     |     /// @param controller Address of the controller
 1293 |     |     /// @param assetsFulfilled Amount of assets fulfilled
 1294 |     |     /// @param sharesFulfilled Amount of shares fulfilled
 1295 |     |     /// @param averageWithdrawPrice Average withdraw price
 1296 |     |     /// @param accumulatorShares Accumulator shares
 1297 |     |     /// @param accumulatorCostBasis Accumulator cost basis
 1298 | *   |     function _onRedeemClaimable(
 1299 |     |         address controller,
 1300 |     |         uint256 assetsFulfilled,
 1301 |     |         uint256 sharesFulfilled,
 1302 |     |         uint256 averageWithdrawPrice,
 1303 |     |         uint256 accumulatorShares,
 1304 |     |         uint256 accumulatorCostBasis
 1305 |     |     ) private {
 1306 | *   |         ISuperVault(_vault).onRedeemClaimable(
 1307 |     |             controller,
 1308 |     |             assetsFulfilled,
 1309 |     |             sharesFulfilled,
 1310 |     |             averageWithdrawPrice,
 1311 |     |             accumulatorShares,
 1312 |     |             accumulatorCostBasis
 1313 |     |         );
 1314 |     |     }
 1315 |     | 
 1316 |     |     /// @notice Internal function to handle a redeem
 1317 |     |     /// @param controller Address of the controller
 1318 |     |     /// @param shares Amount of shares
 1319 | *   |     function _handleRequestRedeem(address controller, uint256 shares) private {
 1320 | *   |         if (shares == 0) revert INVALID_AMOUNT();
 1321 | *   |         if (controller == address(0)) revert ZERO_ADDRESS();
 1322 | *   |         SuperVaultState storage state = superVaultState[controller];
 1323 |     | 
 1324 |     |         // Defense-in-depth: assert controller has accumulator shares
 1325 | *   |         if (state.accumulatorShares == 0) revert INSUFFICIENT_SHARES();
 1326 |     | 
 1327 |     |         // Get current PPS from aggregator to use as baseline for slippage protection
 1328 | *   |         uint256 currentPPS = getStoredPPS();
 1329 | *   |         if (currentPPS == 0) revert INVALID_PPS();
 1330 |     | 
 1331 |     |         // Calculate weighted average of PPS if there's an existing request
 1332 | *   |         if (state.pendingRedeemRequest > 0) {
 1333 |     |             // Calculate weighted average of PPS based on share amounts
 1334 | *   |             uint256 existingSharesInRequest = state.pendingRedeemRequest;
 1335 | *   |             uint256 newTotalSharesInRequest = existingSharesInRequest + shares;
 1336 |     | 
 1337 |     |             // Use weighted average formula: (existingShares * existingPPS + newShares * currentPPS) / totalShares
 1338 | *   |             state.averageRequestPPS =
 1339 | *   |                 ((existingSharesInRequest * state.averageRequestPPS) +
 1340 | *   |                     (shares * currentPPS)) /
 1341 |     |                 newTotalSharesInRequest;
 1342 |     | 
 1343 |     |             // Update total shares
 1344 | *   |             state.pendingRedeemRequest = newTotalSharesInRequest;
 1345 |     |         } else {
 1346 |     |             // First request for this controller
 1347 | *   |             state.pendingRedeemRequest = shares;
 1348 | *   |             state.averageRequestPPS = currentPPS;
 1349 |     |         }
 1350 |     | 
 1351 | *   |         emit RedeemRequestPlaced(controller, controller, shares);
 1352 |     |     }
 1353 |     | 
 1354 |     |     /// @notice Internal function to handle a redeem cancellation
 1355 |     |     /// @param controller Address of the controller
 1356 | *   |     function _handleCancelRedeem(address controller) private {
 1357 | *   |         if (controller == address(0)) revert ZERO_ADDRESS();
 1358 | *   |         SuperVaultState storage state = superVaultState[controller];
 1359 | *   |         uint256 pendingShares = state.pendingRedeemRequest;
 1360 | *   |         if (pendingShares == 0) revert REQUEST_NOT_FOUND();
 1361 |     |         // Only clear pending request metadata
 1362 | *   |         state.pendingRedeemRequest = 0;
 1363 | *   |         state.averageRequestPPS = 0;
 1364 | *   |         emit RedeemRequestCanceled(controller, pendingShares);
 1365 |     |     }
 1366 |     | 
 1367 |     |     /// @notice Internal function to handle a redeem claim
 1368 |     |     /// @param controller Address of the controller
 1369 |     |     /// @param receiver Address of the receiver
 1370 |     |     /// @param assetsToClaim Amount of assets to claim
 1371 | *   |     function _handleClaimRedeem(
 1372 |     |         address controller,
 1373 |     |         address receiver,
 1374 |     |         uint256 assetsToClaim
 1375 | *   |     ) private {
 1376 | *   |         if (assetsToClaim == 0) revert INVALID_AMOUNT();
 1377 | *   |         if (controller == address(0)) revert ZERO_ADDRESS();
 1378 | *   |         SuperVaultState storage state = superVaultState[controller];
 1379 |     | 
 1380 |     |         // Handle dust collection for rounding errors
 1381 | *   |         uint256 actualAmountToClaim = assetsToClaim;
 1382 | *   |         uint256 remainingAssets = _asset.balanceOf(address(this));
 1383 |     | 
 1384 |     |         // If user is requesting slightly more than available due to rounding errors,
 1385 |     |         // and the difference is small (dust), give them the remaining balance
 1386 | *   |         if (
 1387 | *   |             assetsToClaim > remainingAssets &&
 1388 | *   |             assetsToClaim - remainingAssets <= TOLERANCE_CONSTANT
 1389 |     |         ) {
 1390 | *   |             actualAmountToClaim = remainingAssets;
 1391 |     |         }
 1392 |     | 
 1393 | *   |         if (state.maxWithdraw < actualAmountToClaim)
 1394 |     |             revert INVALID_REDEEM_CLAIM();
 1395 | *   |         state.maxWithdraw -= actualAmountToClaim;
 1396 | *   |         _asset.safeTransfer(receiver, actualAmountToClaim);
 1397 | *   |         emit RedeemRequestFulfilled(
 1398 |     |             receiver,
 1399 |     |             controller,
 1400 |     |             actualAmountToClaim,
 1401 | *   |             0
 1402 |     |         );
 1403 |     |     }
 1404 |     | 
 1405 |     |     /// @notice Internal function to safely transfer tokens
 1406 |     |     /// @param token Address of the token
 1407 |     |     /// @param recipient Address to receive the tokens
 1408 |     |     /// @param amount Amount of tokens to transfer
 1409 | *   |     function _safeTokenTransfer(
 1410 |     |         address token,
 1411 |     |         address recipient,
 1412 |     |         uint256 amount
 1413 |     |     ) private {
 1414 | *   |         if (amount > 0) IERC20(token).safeTransfer(recipient, amount);
 1415 |     |     }
 1416 |     | 
 1417 |     |     /// @notice Internal function to get the token balance of an account
 1418 |     |     /// @param token Address of the token
 1419 |     |     /// @param account Address of the account
 1420 |     |     /// @return Token balance of the account
 1421 | *   |     function _getTokenBalance(
 1422 |     |         address token,
 1423 |     |         address account
 1424 | *   |     ) private view returns (uint256) {
 1425 | *   |         return IERC20(token).balanceOf(account);
 1426 |     |     }
 1427 |     | 
 1428 |     |     /// @notice Internal function to get the slippage tolerance
 1429 |     |     /// @return Slippage tolerance
 1430 |     |     function _getSlippageTolerance() private pure returns (uint256) {
 1431 |     |         return SV_SLIPPAGE_TOLERANCE_BPS;
 1432 |     |     }
 1433 |     | 
 1434 |     |     /// @notice Internal function to check if the caller is the vault
 1435 |     |     /// @dev This is used to prevent unauthorized access to certain functions
 1436 | *   |     function _requireVault() internal view {
 1437 | *   |         if (msg.sender != _vault) revert ACCESS_DENIED();
 1438 |     |     }
 1439 |     | 
 1440 |     |     /// @notice Checks if the strategy is currently paused
 1441 |     |     /// @dev This calls SuperVaultAggregator.isStrategyPaused to determine pause status
 1442 |     |     /// @return True if the strategy is paused, false otherwise
 1443 | *   |     function _isPaused() internal view returns (bool) {
 1444 | *   |         return _getSuperVaultAggregator().isStrategyPaused(address(this));
 1445 |     |     }
 1446 |     | 
 1447 |     |     /// @notice Validates a hook using the Merkle root system
 1448 |     |     /// @param hook Address of the hook to validate
 1449 |     |     /// @param hookCalldata Calldata to be passed to the hook
 1450 |     |     /// @param globalProof Merkle proof for the global root
 1451 |     |     /// @param strategyProof Merkle proof for the strategy-specific root
 1452 |     |     /// @return isValid True if the hook is valid, false otherwise
 1453 | *   |     function _validateHook(
 1454 |     |         address hook,
 1455 |     |         bytes memory hookCalldata,
 1456 |     |         bytes32[] memory globalProof,
 1457 |     |         bytes32[] memory strategyProof
 1458 | *   |     ) internal view returns (bool) {
 1459 | *   |         return
 1460 | *   |             _getSuperVaultAggregator().validateHook(
 1461 | *   |                 address(this),
 1462 | *   |                 ISuperVaultAggregator.ValidateHookArgs({
 1463 | *   |                     hookAddress: hook,
 1464 | *   |                     hookArgs: ISuperHookInspector(hook).inspect(hookCalldata),
 1465 | *   |                     globalProof: globalProof,
 1466 | *   |                     strategyProof: strategyProof
 1467 |     |                 })
 1468 |     |             );
 1469 |     |     }
 1470 |     | }
 1471 |     | 

/opt/scfuzzbench/work/target/src/interfaces/ISuperGovernor.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | import "@openzeppelin/contracts/access/IAccessControl.sol";
   5 |     | 
   6 |     | /*//////////////////////////////////////////////////////////////
   7 |     |                                   ENUMS
   8 |     |     //////////////////////////////////////////////////////////////*/
   9 |     | /// @notice Enum representing different types of fees that can be managed
  10 |     | enum FeeType {
  11 |     |     REVENUE_SHARE,
  12 |     |     SUPER_VAULT_PERFORMANCE_FEE,
  13 |     |     SUPER_ASSET_SWAP_FEE
  14 |     | }
  15 |     | /// @title ISuperGovernor
  16 |     | /// @author Superform Labs
  17 |     | /// @notice Interface for the SuperGovernor contract
  18 |     | /// @dev Central registry for all deployed contracts in the Superform periphery
  19 |     | 
  20 |     | interface ISuperGovernor is IAccessControl {
  21 |     |     /*//////////////////////////////////////////////////////////////
  22 |     |                                   STRUCTS
  23 |     |     //////////////////////////////////////////////////////////////*/
  24 |     | 
  25 |     |     /// @notice Structure containing Merkle root data for a hook
  26 |     |     struct HookMerkleRootData {
  27 |     |         bytes32 currentRoot; // Current active Merkle root for the hook
  28 |     |         bytes32 proposedRoot; // Proposed new Merkle root (zero if no proposal exists)
  29 |     |         uint256 effectiveTime; // Timestamp when the proposed root becomes effective
  30 |     |     }
  31 |     | 
  32 |     |     struct GasInfo {
  33 |     |         // `batchForwardPPS` base gas
  34 |     |         uint256 baseGasBatch;
  35 |     |         // `batchForwardPPS` gas increase per entry
  36 |     |         uint256 gasIncreasePerEntryBatch;
  37 |     |     }
  38 |     | 
  39 |     |     /*//////////////////////////////////////////////////////////////
  40 |     |                                   ERRORS
  41 |     |     //////////////////////////////////////////////////////////////*/
  42 |     |     /// @notice Thrown when a function that should only be called by governor is called by someone else
  43 |     |     error ONLY_GOVERNOR();
  44 |     |     /// @notice Thrown when trying to register a contract that is already registered
  45 |     |     error CONTRACT_ALREADY_REGISTERED();
  46 |     |     /// @notice Thrown when trying to access a contract that is not registered
  47 |     |     error CONTRACT_NOT_FOUND();
  48 |     |     /// @notice Thrown when providing an invalid address (typically zero address)
  49 |     |     error INVALID_ADDRESS();
  50 |     |     /// @notice Thrown when providing an invalid chain ID
  51 |     |     error INVALID_CHAIN_ID();
  52 |     |     /// @notice Thrown when a hook is already approved
  53 |     |     error HOOK_ALREADY_APPROVED();
  54 |     |     /// @notice Thrown when a hook is not approved but expected to be
  55 |     |     error HOOK_NOT_APPROVED();
  56 |     |     /// @notice Thrown when a fulfill requests hook is already registered
  57 |     |     error FULFILL_REQUESTS_HOOK_ALREADY_REGISTERED();
  58 |     |     /// @notice Thrown when a fulfill requests hook is not registered but expected to be
  59 |     |     error FULFILL_REQUESTS_HOOK_NOT_REGISTERED();
  60 |     |     /// @notice Thrown when provided revenue share is invalid (exceeds 100%)
  61 |     |     error INVALID_REVENUE_SHARE();
  62 |     |     /// @notice Thrown when an invalid fee value is proposed (must be <= BPS_MAX)
  63 |     |     error INVALID_FEE_VALUE();
  64 |     |     /// @notice Thrown when no proposed fee exists but one is expected
  65 |     |     error NO_PROPOSED_FEE(FeeType feeType);
  66 |     |     /// @notice Thrown when timelock period has not expired
  67 |     |     error TIMELOCK_NOT_EXPIRED();
  68 |     |     /// @notice Thrown when a validator is not registered
  69 |     |     error VALIDATOR_NOT_REGISTERED();
  70 |     |     /// @notice Thrown when a validator is already registered
  71 |     |     error VALIDATOR_ALREADY_REGISTERED();
  72 |     |     /// @notice Thrown when trying to change active PPS oracle directly
  73 |     |     error MUST_USE_TIMELOCK_FOR_CHANGE();
  74 |     |     /// @notice Thrown when a SuperBank hook Merkle root is not registered but expected to be
  75 |     |     error INVALID_TIMESTAMP();
  76 |     |     /// @notice Thrown when attempting to set an invalid quorum value (typically zero)
  77 |     |     error INVALID_QUORUM();
  78 |     |     /// @notice Thrown when no active PPS oracle is set but one is required
  79 |     |     error NO_ACTIVE_PPS_ORACLE();
  80 |     |     /// @notice Thrown when no proposed PPS oracle exists but one is expected
  81 |     |     error NO_PROPOSED_PPS_ORACLE();
  82 |     |     /// @notice Error thrown when manager takeovers are frozen
  83 |     |     error MANAGER_TAKEOVERS_FROZEN();
  84 |     |     /// @notice Thrown when no proposed Merkle root exists but one is expected
  85 |     |     error NO_PROPOSED_MERKLE_ROOT();
  86 |     |     /// @notice Thrown when no proposed Merkle root exists but one is expected
  87 |     |     error ZERO_PROPOSED_MERKLE_ROOT();
  88 |     |     /// @notice Thrown when no proposed minimum staleness exists but one is expected
  89 |     |     error NO_PROPOSED_MIN_STALENESS();
  90 |     |     /// @notice Thrown when the provided maxStaleness is less than the minimum required staleness
  91 |     |     error MAX_STALENESS_TOO_LOW();
  92 |     |     /// @notice Thrown when a relayer is not registered
  93 |     |     error RELAYER_NOT_REGISTERED();
  94 |     |     /// @notice Thrown when a relayer is already registered
  95 |     |     error RELAYER_ALREADY_REGISTERED();
  96 |     |     /// @notice Thrown when an executor is not registered
  97 |     |     error EXECUTOR_NOT_REGISTERED();
  98 |     |     /// @notice Thrown when an executor is already registered
  99 |     |     error EXECUTOR_ALREADY_REGISTERED();
 100 |     |     /// @notice Thrown when there's no pending change but one is expected
 101 |     |     error NO_PENDING_CHANGE();
 102 |     |     /// @notice Thrown when a manager is not registered
 103 |     |     error MANAGER_NOT_REGISTERED();
 104 |     |     /// @notice Thrown when a manager is already registered
 105 |     |     error MANAGER_ALREADY_REGISTERED();
 106 |     |     /// @notice Thrown when a token is already whitelisted
 107 |     |     error TOKEN_ALREADY_WHITELISTED();
 108 |     |     /// @notice Thrown when a token is not proposed for whitelisting but expected to be
 109 |     |     error NOT_PROPOSED_INCENTIVE_TOKEN();
 110 |     |     /// @notice Thrown when a token is not whitelisted but expected to be
 111 |     |     error NOT_WHITELISTED_INCENTIVE_TOKEN();
 112 |     |     /// @notice Thrown when trying to register a keeper that is already registered
 113 |     |     error KEEPER_ALREADY_REGISTERED();
 114 |     |     /// @notice Thrown when trying to unregister a keeper that is not registered
 115 |     |     error KEEPER_NOT_REGISTERED();
 116 |     |     /// @notice Thrown when the price is not found
 117 |     |     error PRICE_NOT_FOUND();
 118 |     |     /// @notice Thrown when the price is stale
 119 |     |     error STALE_ORACLE_PRICE();
 120 |     |     /// @notice Thrown when the super oracle is not found
 121 |     |     error SUPER_ORACLE_NOT_FOUND();
 122 |     |     /// @notice Thrown when the up token is not found
 123 |     |     error UP_NOT_FOUND();
 124 |     |     /// @notice Thrown when the gas info is invalid
 125 |     |     error INVALID_GAS_INFO();
 126 |     | 
 127 |     |     /*//////////////////////////////////////////////////////////////
 128 |     |                                   EVENTS
 129 |     |     //////////////////////////////////////////////////////////////*/
 130 |     |     /// @notice Emitted when an address is set in the registry
 131 |     |     /// @param key The key used to reference the address
 132 |     |     /// @param value The address value
 133 |     |     event AddressSet(bytes32 indexed key, address indexed value);
 134 |     | 
 135 |     |     /// @notice Emitted when a hook is approved
 136 |     |     /// @param hook The address of the approved hook
 137 |     |     event HookApproved(address indexed hook);
 138 |     | 
 139 |     |     /// @notice Emitted when a hook is removed
 140 |     |     /// @param hook The address of the removed hook
 141 |     |     event HookRemoved(address indexed hook);
 142 |     | 
 143 |     |     /// @notice Emitted when a fulfill requests hook is registered
 144 |     |     /// @param hook The address of the registered fulfill requests hook
 145 |     |     event FulfillRequestsHookRegistered(address indexed hook);
 146 |     | 
 147 |     |     /// @notice Emitted when a fulfill requests hook is unregistered
 148 |     |     /// @param hook The address of the unregistered fulfill requests hook
 149 |     |     event FulfillRequestsHookUnregistered(address indexed hook);
 150 |     | 
 151 |     |     /// @notice Emitted when a validator is registered
 152 |     |     /// @param validator The address of the registered validator
 153 |     |     event ValidatorAdded(address indexed validator);
 154 |     | 
 155 |     |     /// @notice Emitted when a validator is removed
 156 |     |     /// @param validator The address of the removed validator
 157 |     |     event ValidatorRemoved(address indexed validator);
 158 |     | 
 159 |     |     /// @notice Emitted when revenue share is updated
 160 |     |     /// @param share The new revenue share percentage
 161 |     |     event RevenueShareUpdated(uint256 share);
 162 |     | 
 163 |     |     /// @notice Emitted when a new fee is proposed
 164 |     |     /// @param feeType The type of fee being proposed
 165 |     |     /// @param value The proposed fee value (in basis points)
 166 |     |     /// @param effectiveTime The timestamp when the fee will be effective
 167 |     |     event FeeProposed(FeeType indexed feeType, uint256 value, uint256 effectiveTime);
 168 |     | 
 169 |     |     /// @notice Emitted when a fee is updated
 170 |     |     /// @param feeType The type of fee being updated
 171 |     |     /// @param value The new fee value (in basis points)
 172 |     |     event FeeUpdated(FeeType indexed feeType, uint256 value);
 173 |     | 
 174 |     |     /// @notice Emitted when a new SuperBank hook Merkle root is proposed
 175 |     |     /// @param hook The hook address for which the Merkle root is being proposed
 176 |     |     /// @param newRoot The new Merkle root
 177 |     |     /// @param effectiveTime The timestamp when the new root will be effective
 178 |     |     event SuperBankHookMerkleRootProposed(address indexed hook, bytes32 newRoot, uint256 effectiveTime);
 179 |     | 
 180 |     |     /// @notice Emitted when the SuperBank hook Merkle root is updated.
 181 |     |     /// @param hook The address of the hook for which the Merkle root was updated.
 182 |     |     /// @param newRoot The new Merkle root.
 183 |     |     event SuperBankHookMerkleRootUpdated(address indexed hook, bytes32 newRoot);
 184 |     | 
 185 |     |     /// @notice Emitted when the VaultBank hook Merkle root is proposed
 186 |     |     /// @param hook The hook address for which the Merkle root is being proposed
 187 |     |     /// @param newRoot The new Merkle root
 188 |     |     /// @param effectiveTime The timestamp when the new root will be effective
 189 |     |     event VaultBankHookMerkleRootProposed(address indexed hook, bytes32 newRoot, uint256 effectiveTime);
 190 |     | 
 191 |     |     /// @notice Emitted when the VaultBank hook Merkle root is updated.
 192 |     |     /// @param hook The address of the hook for which the Merkle root was updated.
 193 |     |     /// @param newRoot The new Merkle root.
 194 |     |     event VaultBankHookMerkleRootUpdated(address indexed hook, bytes32 newRoot);
 195 |     | 
 196 |     |     /// @notice Emitted when the active PPS Oracle's quorum requirement is updated
 197 |     |     /// @param quorum The new quorum value
 198 |     |     event PPSOracleQuorumUpdated(uint256 quorum);
 199 |     | 
 200 |     |     /// @notice Emitted when an active PPS oracle is initially set
 201 |     |     /// @param oracle The address of the set oracle
 202 |     |     event ActivePPSOracleSet(address indexed oracle);
 203 |     | 
 204 |     |     /// @notice Emitted when a new PPS oracle is proposed
 205 |     |     /// @param oracle The address of the proposed oracle
 206 |     |     /// @param effectiveTime The timestamp when the proposal will be effective
 207 |     |     event ActivePPSOracleProposed(address indexed oracle, uint256 effectiveTime);
 208 |     | 
 209 |     |     /// @notice Emitted when the active PPS oracle is changed
 210 |     |     /// @param oldOracle The address of the previous oracle
 211 |     |     /// @param newOracle The address of the new oracle
 212 |     |     event ActivePPSOracleChanged(address indexed oldOracle, address indexed newOracle);
 213 |     | 
 214 |     |     /// @notice Event emitted when manager takeovers are permanently frozen
 215 |     |     event ManagerTakeoversFrozen();
 216 |     | 
 217 |     |     /// @notice Emitted when a relayer is added
 218 |     |     /// @param relayer The address of the added relayer
 219 |     |     event RelayerAdded(address indexed relayer);
 220 |     | 
 221 |     |     /// @notice Emitted when a relayer is removed
 222 |     |     /// @param relayer The address of the removed relayer
 223 |     |     event RelayerRemoved(address indexed relayer);
 224 |     | 
 225 |     |     /// @notice Emitted when a vault bank is added
 226 |     |     /// @param chainId The chain ID of the added vault bank
 227 |     |     /// @param vaultBank The address of the added vault bank
 228 |     |     event VaultBankAddressAdded(uint64 indexed chainId, address indexed vaultBank);
 229 |     | 
 230 |     |     /// @notice Emitted when an executor is added
 231 |     |     /// @param executor The address of the added executor
 232 |     |     event ExecutorAdded(address indexed executor);
 233 |     | 
 234 |     |     /// @notice Emitted when an executor is removed
 235 |     |     /// @param executor The address of the removed executor
 236 |     |     event ExecutorRemoved(address indexed executor);
 237 |     | 
 238 |     |     /// @notice Emitted when a prover is set
 239 |     |     /// @param prover The address of the prover
 240 |     |     event ProverSet(address indexed prover);
 241 |     | 
 242 |     |     /// @notice Emitted when a change to upkeep payments status is proposed
 243 |     |     /// @param enabled The proposed status (enabled/disabled)
 244 |     |     /// @param effectiveTime The timestamp when the status change will be effective
 245 |     |     event UpkeepPaymentsChangeProposed(bool enabled, uint256 effectiveTime);
 246 |     | 
 247 |     |     /// @notice Emitted when upkeep payments status is changed
 248 |     |     /// @param enabled The new status (enabled/disabled)
 249 |     |     event UpkeepPaymentsChanged(bool enabled);
 250 |     | 
 251 |     |     /// @notice Emitted when a new minimum staleness is proposed
 252 |     |     /// @param newMinStaleness The proposed minimum staleness value
 253 |     |     /// @param effectiveTime The timestamp when the new value will be effective
 254 |     |     event MinStalenesProposed(uint256 newMinStaleness, uint256 effectiveTime);
 255 |     | 
 256 |     |     /// @notice Emitted when the minimum staleness is changed
 257 |     |     /// @param newMinStaleness The new minimum staleness value
 258 |     |     event MinStalenesChanged(uint256 newMinStaleness);
 259 |     | 
 260 |     |     /// @notice Emitted when a superform manager is added
 261 |     |     /// @param manager The address of the added manager
 262 |     |     event SuperformManagerAdded(address indexed manager);
 263 |     | 
 264 |     |     /// @notice Emitted when a superform manager is removed
 265 |     |     /// @param manager The address of the removed manager
 266 |     |     event SuperformManagerRemoved(address indexed manager);
 267 |     | 
 268 |     |     /// @notice Emitted when incentive tokens are proposed for whitelisting
 269 |     |     /// @param tokens The addresses of the proposed tokens
 270 |     |     /// @param effectiveTime The timestamp when the proposal will be effective
 271 |     |     event WhitelistedIncentiveTokensProposed(address[] tokens, uint256 effectiveTime);
 272 |     | 
 273 |     |     /// @notice Emitted when whitelisted incentive tokens are added
 274 |     |     /// @param tokens The addresses of the added tokens
 275 |     |     event WhitelistedIncentiveTokensAdded(address[] tokens);
 276 |     | 
 277 |     |     /// @notice Emitted when whitelisted incentive tokens are removed
 278 |     |     /// @param tokens The addresses of the removed tokens
 279 |     |     event WhitelistedIncentiveTokensRemoved(address[] tokens);
 280 |     | 
 281 |     |     /// @notice Emitted when a protected keeper is registered
 282 |     |     /// @param keeper Address of the keeper being registered
 283 |     |     event ProtectedKeeperRegistered(address indexed keeper);
 284 |     | 
 285 |     |     /// @notice Emitted when a protected keeper is unregistered
 286 |     |     /// @param keeper Address of the keeper being unregistered
 287 |     |     event ProtectedKeeperUnregistered(address indexed keeper);
 288 |     | 
 289 |     |     /// @notice Emitted when gas info is set
 290 |     |     /// @param oracle The address of the oracle
 291 |     |     /// @param baseGasBatch The base gas for the oracle
 292 |     |     /// @param gasIncreasePerEntryBatch The gas increase per entry for the oracle
 293 |     |     event GasInfoSet(address indexed oracle, uint256 baseGasBatch, uint256 gasIncreasePerEntryBatch);
 294 |     | 
 295 |     |     /*//////////////////////////////////////////////////////////////
 296 |     |                        CONTRACT REGISTRY FUNCTIONS
 297 |     |     //////////////////////////////////////////////////////////////*/
 298 |     |     /// @notice Sets an address in the registry
 299 |     |     /// @param key The key to associate with the address
 300 |     |     /// @param value The address value
 301 |     |     function setAddress(bytes32 key, address value) external;
 302 |     | 
 303 |     |     /*//////////////////////////////////////////////////////////////
 304 |     |                         PERIPHERY CONFIGURATIONS
 305 |     |     //////////////////////////////////////////////////////////////*/
 306 |     |     /// @notice Sets the prover address
 307 |     |     /// @param prover The address of the prover
 308 |     |     function setProver(address prover) external;
 309 |     | 
 310 |     |     /// @notice Change the primary manager for a strategy
 311 |     |     /// @dev Only SuperGovernor can call this function directly
 312 |     |     /// @param strategy The strategy address
 313 |     |     /// @param newManager The new primary manager address
 314 |     |     function changePrimaryManager(address strategy, address newManager) external;
 315 |     | 
 316 |     |     /// @notice Permanently freezes all manager takeovers globally
 317 |     |     function freezeManagerTakeover() external;
 318 |     | 
 319 |     |     /// @notice Changes the hooks root update timelock duration
 320 |     |     /// @param newTimelock New timelock duration in seconds
 321 |     |     function changeHooksRootUpdateTimelock(uint256 newTimelock) external;
 322 |     | 
 323 |     |     /// @notice Proposes a new global hooks Merkle root
 324 |     |     /// @dev Only GOVERNOR_ROLE can call this function
 325 |     |     /// @param newRoot New Merkle root for global hooks validation
 326 |     |     function proposeGlobalHooksRoot(bytes32 newRoot) external;
 327 |     | 
 328 |     |     /// @notice Sets veto status for global hooks Merkle root
 329 |     |     /// @dev Only GUARDIAN_ROLE can call this function
 330 |     |     /// @param vetoed Whether to veto (true) or unveto (false) the global hooks root
 331 |     |     function setGlobalHooksRootVetoStatus(bool vetoed) external;
 332 |     | 
 333 |     |     /// @notice Sets veto status for a strategy-specific hooks Merkle root
 334 |     |     /// @dev Only GUARDIAN_ROLE can call this function
 335 |     |     /// @param strategy Address of the strategy to affect
 336 |     |     /// @param vetoed Whether to veto (true) or unveto (false) the strategy hooks root
 337 |     |     function setStrategyHooksRootVetoStatus(address strategy, bool vetoed) external;
 338 |     | 
 339 |     |     /// @notice Sets the superasset manager for a superasset
 340 |     |     /// @param superAsset The superasset address
 341 |     |     /// @param superAssetManager The new superasset manager address
 342 |     |     function setSuperAssetManager(address superAsset, address superAssetManager) external;
 343 |     | 
 344 |     |     /// @notice Adds an ICC to the whitelist
 345 |     |     /// @param icc The ICC address to add
 346 |     |     function addICCToWhitelist(address icc) external;
 347 |     | 
 348 |     |     /// @notice Removes an ICC from the whitelist
 349 |     |     /// @param icc The ICC address to remove
 350 |     |     function removeICCFromWhitelist(address icc) external;
 351 |     | 
 352 |     |     /// @notice Sets the maximum staleness period for all oracle feeds
 353 |     |     /// @param newMaxStaleness The new maximum staleness period in seconds
 354 |     |     function setOracleMaxStaleness(uint256 newMaxStaleness) external;
 355 |     | 
 356 |     |     /// @notice Sets the maximum staleness period for a specific oracle feed
 357 |     |     /// @param feed The address of the feed to set staleness for
 358 |     |     /// @param newMaxStaleness The new maximum staleness period in seconds
 359 |     |     function setOracleFeedMaxStaleness(address feed, uint256 newMaxStaleness) external;
 360 |     | 
 361 |     |     /// @notice Sets the maximum staleness periods for multiple oracle feeds in batch
 362 |     |     /// @param feeds The addresses of the feeds to set staleness for
 363 |     |     /// @param newMaxStalenessList The new maximum staleness periods in seconds
 364 |     |     function setOracleFeedMaxStalenessBatch(
 365 |     |         address[] calldata feeds,
 366 |     |         uint256[] calldata newMaxStalenessList
 367 |     |     )
 368 |     |         external;
 369 |     | 
 370 |     |     /// @notice Queues an oracle update for execution after timelock period
 371 |     |     /// @param bases Base asset addresses
 372 |     |     /// @param quotes Quote asset addresses
 373 |     |     /// @param providers Provider identifiers
 374 |     |     /// @param feeds Feed addresses
 375 |     |     function queueOracleUpdate(
 376 |     |         address[] calldata bases,
 377 |     |         address[] calldata quotes,
 378 |     |         bytes32[] calldata providers,
 379 |     |         address[] calldata feeds
 380 |     |     )
 381 |     |         external;
 382 |     | 
 383 |     |     /// @notice Queues a provider removal for execution after timelock period
 384 |     |     /// @param providers The providers to remove
 385 |     |     function queueOracleProviderRemoval(bytes32[] calldata providers) external;
 386 |     | 
 387 |     |     /// @notice Sets uptime feeds for multiple data oracles in batch (Layer 2 only)
 388 |     |     /// @param dataOracles Array of data oracle addresses to set uptime feeds for
 389 |     |     /// @param uptimeOracles Array of uptime feed addresses to set
 390 |     |     /// @param gracePeriods Array of grace periods in seconds after sequencer restart
 391 |     |     function batchSetOracleUptimeFeed(
 392 |     |         address[] calldata dataOracles,
 393 |     |         address[] calldata uptimeOracles,
 394 |     |         uint256[] calldata gracePeriods
 395 |     |     )
 396 |     |         external;
 397 |     | 
 398 |     |     /// @notice Sets the emergency price for a token
 399 |     |     /// @param token The address of the token
 400 |     |     /// @param price The emergency price to set
 401 |     |     function setEmergencyPrice(address token, uint256 price) external;
 402 |     | 
 403 |     |     /// @notice Sets the emergency price for multiple tokens o
 404 |     |     /// @param tokens Array of token addresses
 405 |     |     /// @param prices Array of emergency prices
 406 |     |     function batchSetEmergencyPrices(address[] calldata tokens, uint256[] calldata prices) external;
 407 |     | 
 408 |     |     /*//////////////////////////////////////////////////////////////
 409 |     |                           HOOK MANAGEMENT
 410 |     |     //////////////////////////////////////////////////////////////*/
 411 |     |     /// @notice Registers a hook for use in SuperVaults
 412 |     |     /// @param hook The address of the hook to register
 413 |     |     /// @param isFulfillRequestsHook Whether the hook is a fulfill requests hook
 414 |     |     function registerHook(address hook, bool isFulfillRequestsHook) external;
 415 |     | 
 416 |     |     /// @notice Unregisters a hook from the approved list
 417 |     |     /// @param hook The address of the hook to unregister
 418 |     |     function unregisterHook(address hook) external;
 419 |     | 
 420 |     |     /*//////////////////////////////////////////////////////////////
 421 |     |                         EXECUTOR MANAGEMENT
 422 |     |     //////////////////////////////////////////////////////////////*/
 423 |     |     /// @notice Adds an executor to the approved list
 424 |     |     /// @param executor The address of the executor to add
 425 |     |     function addExecutor(address executor) external;
 426 |     | 
 427 |     |     /// @notice Removes an executor from the approved list
 428 |     |     /// @param executor The address of the executor to remove
 429 |     |     function removeExecutor(address executor) external;
 430 |     | 
 431 |     |     /*//////////////////////////////////////////////////////////////
 432 |     |                         RELAYER MANAGEMENT
 433 |     |     //////////////////////////////////////////////////////////////*/
 434 |     |     /// @notice Adds a relayer to the approved list
 435 |     |     /// @param relayer The address of the relayer to add
 436 |     |     function addRelayer(address relayer) external;
 437 |     | 
 438 |     |     /// @notice Removes a relayer from the approved list
 439 |     |     /// @param relayer The address of the relayer to remove
 440 |     |     function removeRelayer(address relayer) external;
 441 |     | 
 442 |     |     /*//////////////////////////////////////////////////////////////
 443 |     |                       VALIDATOR MANAGEMENT
 444 |     |     //////////////////////////////////////////////////////////////*/
 445 |     |     /// @notice Adds a validator to the approved list
 446 |     |     /// @param validator The address of the validator to add
 447 |     |     function addValidator(address validator) external;
 448 |     | 
 449 |     |     /// @notice Removes a validator from the approved list
 450 |     |     /// @param validator The address of the validator to remove
 451 |     |     function removeValidator(address validator) external;
 452 |     | 
 453 |     |     /*//////////////////////////////////////////////////////////////
 454 |     |                        PPS ORACLE MANAGEMENT
 455 |     |     //////////////////////////////////////////////////////////////*/
 456 |     |     /// @notice Sets the active PPS oracle (only if there is no active oracle yet)
 457 |     |     /// @param oracle Address of the PPS oracle to set as active
 458 |     |     function setActivePPSOracle(address oracle) external;
 459 |     | 
 460 |     |     /// @notice Proposes a new active PPS oracle (when there is already an active one)
 461 |     |     /// @param oracle Address of the PPS oracle to propose as active
 462 |     |     function proposeActivePPSOracle(address oracle) external;
 463 |     | 
 464 |     |     /// @notice Executes a previously proposed PPS oracle change after timelock has expired
 465 |     |     function executeActivePPSOracleChange() external;
 466 |     | 
 467 |     |     /// @notice Sets the quorum requirement for the active PPS Oracle
 468 |     |     /// @param quorum The new quorum value
 469 |     |     function setPPSOracleQuorum(uint256 quorum) external;
 470 |     | 
 471 |     |     /*//////////////////////////////////////////////////////////////
 472 |     |                       REVENUE SHARE MANAGEMENT
 473 |     |     //////////////////////////////////////////////////////////////*/
 474 |     |     /// @notice Proposes a new fee value
 475 |     |     /// @param feeType The type of fee to propose
 476 |     |     /// @param value The proposed fee value (in basis points)
 477 |     |     function proposeFee(FeeType feeType, uint256 value) external;
 478 |     | 
 479 |     |     /// @notice Executes a previously proposed fee update after timelock has expired
 480 |     |     /// @param feeType The type of ffee to execute the update for
 481 |     |     function executeFeeUpdate(FeeType feeType) external;
 482 |     | 
 483 |     |     /// @notice Executes an upkeep claim on `SuperVaultAggregator`
 484 |     |     /// @param amount The amount to claim
 485 |     |     function executeUpkeepClaim(uint256 amount) external;
 486 |     | 
 487 |     |     /*//////////////////////////////////////////////////////////////
 488 |     |                       UPKEEP COST MANAGEMENT
 489 |     |     //////////////////////////////////////////////////////////////*/
 490 |     |     /// @notice Sets gas info for an oracle
 491 |     |     /// @param oracle The address of the oracle
 492 |     |     /// @param baseGasBatch The base gas for the oracle
 493 |     |     /// @param gasIncreasePerEntryBatch The gas increase per entry for the oracle
 494 |     |     function setGasInfo(address oracle, uint256 baseGasBatch, uint256 gasIncreasePerEntryBatch) external;
 495 |     | 
 496 |     |     /// @notice Proposes a change to upkeep payments enabled status
 497 |     |     /// @param enabled The proposed enabled status
 498 |     |     function proposeUpkeepPaymentsChange(bool enabled) external;
 499 |     | 
 500 |     |     /// @notice Executes a previously proposed upkeep payments status change
 501 |     |     function executeUpkeepPaymentsChange() external;
 502 |     | 
 503 |     |     /*//////////////////////////////////////////////////////////////
 504 |     |                         MIN STALENESS MANAGEMENT
 505 |     |     //////////////////////////////////////////////////////////////*/
 506 |     |     /// @notice Proposes a new minimum staleness value to prevent maxStaleness from being set too low
 507 |     |     /// @param newMinStaleness The proposed new minimum staleness value in seconds
 508 |     |     function proposeMinStaleness(uint256 newMinStaleness) external;
 509 |     | 
 510 |     |     /// @notice Executes a previously proposed minimum staleness change after timelock has expired
 511 |     |     function executeMinStalenesChange() external;
 512 |     | 
 513 |     |     /*//////////////////////////////////////////////////////////////
 514 |     |                         SUPERFORM MANAGER MANAGEMENT
 515 |     |     //////////////////////////////////////////////////////////////*/
 516 |     | 
 517 |     |     /// @notice Adds a manager to the superform managers list
 518 |     |     /// @param manager Address of the manager to add
 519 |     |     function addSuperformManager(address manager) external;
 520 |     | 
 521 |     |     /// @notice Removes a manager from the superform managers list
 522 |     |     /// @param manager Address of the manager to remove
 523 |     |     function removeSuperformManager(address manager) external;
 524 |     | 
 525 |     |     /*//////////////////////////////////////////////////////////////
 526 |     |                            VAULT HOOKS MGMT
 527 |     |     //////////////////////////////////////////////////////////////*/
 528 |     |     /// @notice Proposes a new Merkle root for a specific hook's allowed targets.
 529 |     |     /// @param hook The address of the hook to update the Merkle root for.
 530 |     |     /// @param proposedRoot The proposed new Merkle root.
 531 |     |     function proposeVaultBankHookMerkleRoot(address hook, bytes32 proposedRoot) external;
 532 |     | 
 533 |     |     /// @notice Executes a previously proposed Merkle root update for a specific hook if the effective time has passed.
 534 |     |     /// @param hook The address of the hook to execute the update for.
 535 |     |     function executeVaultBankHookMerkleRootUpdate(address hook) external;
 536 |     | 
 537 |     |     /*//////////////////////////////////////////////////////////////
 538 |     |                            SUPERBANK HOOKS MGMT
 539 |     |     //////////////////////////////////////////////////////////////*/
 540 |     |     /// @notice Proposes a new Merkle root for a specific hook's allowed targets.
 541 |     |     /// @param hook The address of the hook to update the Merkle root for.
 542 |     |     /// @param proposedRoot The proposed new Merkle root.
 543 |     |     function proposeSuperBankHookMerkleRoot(address hook, bytes32 proposedRoot) external;
 544 |     | 
 545 |     |     /// @notice Executes a previously proposed Merkle root update for a specific hook if the effective time has passed.
 546 |     |     /// @param hook The address of the hook to execute the update for.
 547 |     |     function executeSuperBankHookMerkleRootUpdate(address hook) external;
 548 |     | 
 549 |     |     /*//////////////////////////////////////////////////////////////
 550 |     |                         VAULT BANK MANAGEMENT
 551 |     |     //////////////////////////////////////////////////////////////*/
 552 |     |     /// @notice Adds a vault bank address for a specific chain ID
 553 |     |     /// @param chainId The chain ID to add the vault bank for
 554 |     |     /// @param vaultBank The address of the vault bank to add
 555 |     |     function addVaultBank(uint64 chainId, address vaultBank) external;
 556 |     | 
 557 |     |     /*//////////////////////////////////////////////////////////////
 558 |     |                         INCENTIVE TOKEN MANAGEMENT
 559 |     |     //////////////////////////////////////////////////////////////*/
 560 |     |     /// @notice Proposes whitelisted incentive tokens
 561 |     |     /// @param tokens The addresses of the tokens to add
 562 |     |     function proposeAddIncentiveTokens(address[] memory tokens) external;
 563 |     | 
 564 |     |     /// @notice Executes a previously proposed whitelisted incentive token update after timelock has expired
 565 |     |     function executeAddIncentiveTokens() external;
 566 |     | 
 567 |     |     /// @notice Proposes a new whitelisted incentive token
 568 |     |     /// @param tokens The addresses of the tokens to add
 569 |     |     function proposeRemoveIncentiveTokens(address[] memory tokens) external;
 570 |     | 
 571 |     |     /// @notice Executes a previously proposed whitelisted incentive tokens removal after timelock has expired
 572 |     |     function executeRemoveIncentiveTokens() external;
 573 |     | 
 574 |     |     /*//////////////////////////////////////////////////////////////
 575 |     |                         EXTERNAL VIEW FUNCTIONS
 576 |     |     //////////////////////////////////////////////////////////////*/
 577 |     |     /// @notice The identifier of the role that grants access to critical governance functions
 578 |     |     function SUPER_GOVERNOR_ROLE() external view returns (bytes32);
 579 |     | 
 580 |     |     /// @notice The identifier of the role that grants access to daily operations like hooks and validators
 581 |     |     function GOVERNOR_ROLE() external view returns (bytes32);
 582 |     | 
 583 |     |     /// @notice The identifier of the role that grants access to bank management functions
 584 |     |     function BANK_MANAGER_ROLE() external view returns (bytes32);
 585 |     | 
 586 |     |     /// @notice The identifier of the role that grants access to gas management functions
 587 |     |     function GAS_MANAGER_ROLE() external view returns (bytes32);
 588 |     | 
 589 |     |     /// @notice The identifier of the role that grants access to guardian functions
 590 |     |     function GUARDIAN_ROLE() external view returns (bytes32);
 591 |     | 
 592 |     |     /// @notice The identifier of the role that grants access to superasset factory
 593 |     |     function SUPER_ASSET_FACTORY() external view returns (bytes32);
 594 |     | 
 595 |     |     /// @notice Gets an address from the registry
 596 |     |     /// @param key The key of the address to get
 597 |     |     /// @return The address value
 598 |     |     function getAddress(bytes32 key) external view returns (address);
 599 |     | 
 600 |     |     /// @notice Checks if manager takeovers are frozen
 601 |     |     /// @return True if manager takeovers are frozen, false otherwise
 602 |     |     function isManagerTakeoverFrozen() external view returns (bool);
 603 |     | 
 604 |     |     /// @notice Gets the vault bank address for a specific chain ID
 605 |     |     /// @param chainId The chain ID to get the vault bank for
 606 |     |     /// @return The vault bank address
 607 |     |     function getVaultBank(uint64 chainId) external view returns (address);
 608 |     | 
 609 |     |     /// @notice Checks if a hook is registered
 610 |     |     /// @param hook The address of the hook to check
 611 |     |     /// @return True if the hook is registered, false otherwise
 612 |     |     function isHookRegistered(address hook) external view returns (bool);
 613 |     | 
 614 |     |     /// @notice Checks if a hook is registered as a fulfill requests hook
 615 |     |     /// @param hook The address of the hook to check
 616 |     |     /// @return True if the hook is registered as a fulfill requests hook, false otherwise
 617 |     |     function isFulfillRequestsHookRegistered(address hook) external view returns (bool);
 618 |     | 
 619 |     |     /// @notice Gets all registered hooks
 620 |     |     /// @return An array of registered hook addresses
 621 |     |     function getRegisteredHooks() external view returns (address[] memory);
 622 |     | 
 623 |     |     /// @notice Gets all registered fulfill requests hooks
 624 |     |     /// @return An array of registered fulfill requests hook addresses
 625 |     |     function getRegisteredFulfillRequestsHooks() external view returns (address[] memory);
 626 |     | 
 627 |     |     /// @notice Checks if an address is an approved validator
 628 |     |     /// @param validator The address to check
 629 |     |     /// @return True if the address is an approved validator, false otherwise
 630 |     |     function isValidator(address validator) external view returns (bool);
 631 |     | 
 632 |     |     /// @notice Checks if an address has the guardian role
 633 |     |     /// @param guardian Address to check
 634 |     |     /// @return true if the address has the GUARDIAN_ROLE
 635 |     |     function isGuardian(address guardian) external view returns (bool);
 636 |     | 
 637 |     |     /// @notice Checks if an address is an approved relayer
 638 |     |     /// @param relayer The address to check
 639 |     |     /// @return True if the address is an approved relayer, false otherwise
 640 |     |     function isRelayer(address relayer) external view returns (bool);
 641 |     | 
 642 |     |     /// @notice Checks if an address is an approved executor
 643 |     |     /// @param executor The address to check
 644 |     |     /// @return True if the address is an approved executor, false otherwise
 645 |     |     function isExecutor(address executor) external view returns (bool);
 646 |     | 
 647 |     |     /// @notice Returns all registered validators
 648 |     |     /// @return List of validator addresses
 649 |     |     function getValidators() external view returns (address[] memory);
 650 |     | 
 651 |     |     /// @notice Returns all registered relayers
 652 |     |     /// @return List of relayer addresses
 653 |     |     function getRelayers() external view returns (address[] memory);
 654 |     | 
 655 |     |     /// @notice Returns all registered executors
 656 |     |     /// @return List of executor addresses
 657 |     |     function getExecutors() external view returns (address[] memory);
 658 |     | 
 659 |     |     /// @notice Gets the proposed active PPS oracle and its effective time
 660 |     |     /// @return proposedOracle The proposed oracle address
 661 |     |     /// @return effectiveTime The timestamp when the proposed oracle will become effective
 662 |     |     function getProposedActivePPSOracle() external view returns (address proposedOracle, uint256 effectiveTime);
 663 |     | 
 664 |     |     /// @notice Gets the current quorum requirement for the active PPS Oracle
 665 |     |     /// @return The current quorum requirement
 666 |     |     function getPPSOracleQuorum() external view returns (uint256);
 667 |     | 
 668 |     |     /// @notice Gets the active PPS oracle
 669 |     |     /// @return The active PPS oracle address
 670 |     |     function getActivePPSOracle() external view returns (address);
 671 |     | 
 672 |     |     /// @notice Checks if an address is the current active PPS oracle
 673 |     |     /// @param oracle The address to check
 674 |     |     /// @return True if the address is the active PPS oracle, false otherwise
 675 |     |     function isActivePPSOracle(address oracle) external view returns (bool);
 676 |     | 
 677 |     |     /// @notice Gets the current fee value for a specific fee type
 678 |     |     /// @param feeType The type of fee to get
 679 |     |     /// @return The current fee value (in basis points)
 680 |     |     function getFee(FeeType feeType) external view returns (uint256);
 681 |     | 
 682 |     |     /// @notice Gets the current upkeep cost per batch update for PPS updates
 683 |     |     /// @param oracle The address of the PPS oracle
 684 |     |     /// @param chargeableEntries The number of chargeable entries
 685 |     |     /// @return The current upkeep cost per batch update in UP tokens
 686 |     |     function getUpkeepCostPerBatchUpdate(address oracle, uint256 chargeableEntries) external view returns (uint256);
 687 |     | 
 688 |     |     /// @notice Gets the proposed upkeep cost per update and its effective time
 689 |     |     /// @notice Gets the current minimum staleness value
 690 |     |     /// @return The current minimum staleness value in seconds
 691 |     |     function getMinStaleness() external view returns (uint256);
 692 |     | 
 693 |     |     /// @notice Gets the proposed minimum staleness value and its effective time
 694 |     |     /// @return proposedMinStaleness The proposed new minimum staleness value
 695 |     |     /// @return effectiveTime The timestamp when the new value will become effective
 696 |     |     function getProposedMinStaleness() external view returns (uint256 proposedMinStaleness, uint256 effectiveTime);
 697 |     | 
 698 |     |     /// @notice Returns the current Merkle root for a specific hook's allowed targets.
 699 |     |     /// @param hook The address of the hook to get the Merkle root for.
 700 |     |     /// @return The Merkle root for the hook's allowed targets.
 701 |     |     function getSuperBankHookMerkleRoot(address hook) external view returns (bytes32);
 702 |     | 
 703 |     |     /// @notice Returns the current Merkle root for a specific hook's allowed targets.
 704 |     |     /// @param hook The address of the hook to get the Merkle root for.
 705 |     |     /// @return The Merkle root for the hook's allowed targets.
 706 |     |     function getVaultBankHookMerkleRoot(address hook) external view returns (bytes32);
 707 |     | 
 708 |     |     /// @notice Gets the proposed Merkle root and its effective time for a specific hook.
 709 |     |     /// @param hook The address of the hook to get the proposed Merkle root for.
 710 |     |     /// @return proposedRoot The proposed Merkle root.
 711 |     |     /// @return effectiveTime The timestamp when the proposed root will become effective.
 712 |     |     function getProposedSuperBankHookMerkleRoot(address hook)
 713 |     |         external
 714 |     |         view
 715 |     |         returns (bytes32 proposedRoot, uint256 effectiveTime);
 716 |     | 
 717 |     |     /// @notice Gets the proposed Merkle root and its effective time for a specific hook.
 718 |     |     /// @param hook The address of the hook to get the proposed Merkle root for.
 719 |     |     /// @return proposedRoot The proposed Merkle root.
 720 |     |     /// @return effectiveTime The timestamp when the proposed root will become effective.
 721 |     |     function getProposedVaultBankHookMerkleRoot(address hook)
 722 |     |         external
 723 |     |         view
 724 |     |         returns (bytes32 proposedRoot, uint256 effectiveTime);
 725 |     | 
 726 |     |     /// @notice Checks if a token is whitelisted as an incentive token
 727 |     |     /// @param token The address of the token to check
 728 |     |     /// @return True if the token is whitelisted as an incentive token, false otherwise
 729 |     |     function isWhitelistedIncentiveToken(address token) external view returns (bool);
 730 |     | 
 731 |     |     /// @notice Gets the prover address
 732 |     |     /// @return The address of the prover
 733 |     |     function getProver() external view returns (address);
 734 |     | 
 735 |     |     /// @notice Checks if upkeep payments are currently enabled
 736 |     |     /// @return enabled True if upkeep payments are enabled
 737 |     |     function isUpkeepPaymentsEnabled() external view returns (bool);
 738 |     | 
 739 |     |     /// @notice Gets the proposed upkeep payments status and effective time
 740 |     |     /// @return enabled The proposed status
 741 |     |     /// @return effectiveTime The timestamp when the change becomes effective
 742 |     |     function getProposedUpkeepPaymentsStatus() external view returns (bool enabled, uint256 effectiveTime);
 743 |     | 
 744 |     |     /// @notice Checks if an address is a registered superform manager
 745 |     |     /// @param manager The address to check
 746 |     |     /// @return isSuperform True if the address is a superform manager
 747 |     |     function isSuperformManager(address manager) external view returns (bool);
 748 |     | 
 749 |     |     /// @notice Gets the list of all superform managers
 750 |     |     /// @return managers The list of all superform manager addresses
 751 |     |     function getAllSuperformManagers() external view returns (address[] memory);
 752 |     | 
 753 |     |     /// @notice Returns up to `limit` superform managers starting from `cursor`
 754 |     |     /// @param cursor The index to start reading from (0 … len-1)
 755 |     |     /// @param limit The maximum number of records to return
 756 |     |     /// @return chunkOfManagers The array slice [cursor … cursor+limit-1]
 757 |     |     /// @return next The next cursor value the caller should use, or 0 to indicate done
 758 |     |     function getManagersPaginated(
 759 |     |         uint256 cursor,
 760 |     |         uint256 limit
 761 |     |     )
 762 |     |         external
 763 |     |         view
 764 |     |         returns (address[] memory chunkOfManagers, uint256 next);
 765 |     | 
 766 |     |     /// @notice Gets the number of superform managers
 767 |     |     /// @return The number of superform managers
 768 |     |     function getSuperformManagersCount() external view returns (uint256);
 769 |     | 
 770 |     |     /// @notice Gets the SUP ID
 771 |     |     /// @return The ID of the SUP token
 772 |     |     function SUP() external view returns (bytes32);
 773 |     | 
 774 |     |     /// @notice Gets the UP ID
 775 |     |     /// @return The ID of the UP token
 776 |     |     function UP() external view returns (bytes32);
 777 |     | 
 778 |     |     /// @notice Gets the Treasury ID
 779 |     |     /// @return The ID for the Treasury in the registry
 780 |     |     function TREASURY() external view returns (bytes32);
 781 |     | 
 782 |     |     /// @notice Gets the SuperOracle ID
 783 |     |     /// @return The ID for the SuperOracle in the registry
 784 |     |     function SUPER_ORACLE() external view returns (bytes32);
 785 |     | 
 786 |     |     /// @notice Gets the ECDSA PPS Oracle ID
 787 |     |     /// @return The ID for the ECDSA PPS Oracle in the registry
 788 |     |     function ECDSAPPSORACLE() external view returns (bytes32);
 789 |     | 
 790 |     |     /// @notice Gets the SuperVaultAggregator ID
 791 |     |     /// @return The ID for the SuperVaultAggregator in the registry
 792 |     |     function SUPER_VAULT_AGGREGATOR() external view returns (bytes32);
 793 |     | 
 794 |     |     /// @notice Gets the SuperBank ID
 795 |     |     /// @return The ID for the SuperBank in the registry
 796 |     |     function SUPER_BANK() external view returns (bytes32);
 797 |     | 
 798 |     |     /// @notice Registers a keeper that cannot be added as authorized caller by managers
 799 |     |     /// @dev Only governance can register protected keepers
 800 |     |     /// @param keeper Address of the keeper to register
 801 |     |     function registerProtectedKeeper(address keeper) external;
 802 |     | 
 803 |     |     /// @notice Unregisters a protected keeper
 804 |     |     /// @dev Only governance can unregister protected keepers
 805 |     |     /// @param keeper Address of the keeper to unregister
 806 |     |     function unregisterProtectedKeeper(address keeper) external;
 807 |     | 
 808 |     |     /// @notice Checks if an address is a registered protected keeper
 809 |     |     /// @param keeper Address to check
 810 |     |     /// @return True if the address is a registered protected keeper
 811 |     |     function isProtectedKeeper(address keeper) external view returns (bool);
 812 |     | 
 813 |     |     /// @notice Gets all registered protected keepers
 814 |     |     /// @return Array of all registered protected keeper addresses
 815 |     |     function getProtectedKeepers() external view returns (address[] memory);
 816 |     | 
 817 |     |     /// @notice Gets the number of registered protected keepers
 818 |     |     /// @return The number of registered protected keepers
 819 |     |     function getProtectedKeepersCount() external view returns (uint256);
 820 |     | 
 821 |     |     /// @notice Gets the gas info for a specific SuperVault PPS Oracle
 822 |     |     /// @param oracle_ The address of the oracle to get gas info for
 823 |     |     /// @return The gas info for the specified oracle
 824 |     |     function getGasInfo(address oracle_) external view returns (GasInfo memory);
 825 |     | }
 826 |     | 

/opt/scfuzzbench/work/target/src/interfaces/SuperAsset/ISuperAssetFactory.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | /**
   5 |     |  * @title ISuperAssetFactory
   6 |     |  * @notice Interface for the SuperAssetFactory contract which deploys SuperAsset and its dependencies
   7 |     |  */
   8 |     | interface ISuperAssetFactory {
   9 |     |     /*//////////////////////////////////////////////////////////////
  10 |     |                             EVENTS
  11 |     |     //////////////////////////////////////////////////////////////*/
  12 |     | 
  13 |     |     /// @notice Emitted when a new SuperAsset and its dependencies are created
  14 |     |     /// @param superAsset Address of the deployed SuperAsset contract
  15 |     |     /// @param incentiveFund Address of the deployed IncentiveFundContract
  16 |     |     /// @param incentiveCalc Address of the deployed IncentiveCalculationContract
  17 |     |     /// @param name Name of the SuperAsset token
  18 |     |     /// @param symbol Symbol of the SuperAsset token
  19 |     |     event SuperAssetCreated(
  20 |     |         address indexed superAsset, address indexed incentiveFund, address incentiveCalc, string name, string symbol
  21 |     |     );
  22 |     | 
  23 |     |     /*//////////////////////////////////////////////////////////////
  24 |     |                             ERRORS
  25 |     |     //////////////////////////////////////////////////////////////*/
  26 |     | 
  27 |     |     /// @notice Thrown when an address parameter is zero
  28 |     |     error ZERO_ADDRESS();
  29 |     | 
  30 |     |     /// @notice Thrown when the caller is not authorized
  31 |     |     error UNAUTHORIZED();
  32 |     | 
  33 |     |     /// @notice Thrown when ICC is not whitelisted
  34 |     |     error ICC_NOT_WHITELISTED();
  35 |     | 
  36 |     |     /*//////////////////////////////////////////////////////////////
  37 |     |                             STRUCTS
  38 |     |     //////////////////////////////////////////////////////////////*/
  39 |     | 
  40 |     |     /// @notice Parameters required for creating a new SuperAsset
  41 |     |     /// @param name Name of the SuperAsset token
  42 |     |     /// @param symbol Symbol of the SuperAsset token
  43 |     |     /// @param swapFeeInPercentage Initial swap fee percentage for deposits
  44 |     |     /// @param swapFeeOutPercentage Initial swap fee percentage for redemptions
  45 |     |     /// @param asset Address of the primary asset
  46 |     |     /// @param superAssetManager Address of the manager
  47 |     |     /// @param superAssetStrategist Address of the strategist
  48 |     |     /// @param incentiveFundManager Address of the incentive fund manager
  49 |     |     /// @param incentiveCalculationContract Address of the incentive calculation contract
  50 |     |     /// @param tokenInIncentive Address of the token for incoming incentives
  51 |     |     /// @param tokenOutIncentive Address of the token for outgoing incentives
  52 |     |     struct AssetCreationParams {
  53 |     |         string name;
  54 |     |         string symbol;
  55 |     |         uint256 swapFeeInPercentage;
  56 |     |         uint256 swapFeeOutPercentage;
  57 |     |         address asset;
  58 |     |         address superAssetManager;
  59 |     |         address superAssetStrategist;
  60 |     |         address incentiveFundManager;
  61 |     |         address incentiveCalculationContract;
  62 |     |         address tokenInIncentive;
  63 |     |         address tokenOutIncentive;
  64 |     |     }
  65 |     | 
  66 |     |     /// @notice Data for a SuperAsset
  67 |     |     /// @param superAssetStrategist Address of the strategist
  68 |     |     /// @param superAssetManager Address of the manager
  69 |     |     /// @param incentiveFundManager Address of the incentive fund manager
  70 |     |     /// @param incentiveCalculationContract Address of the incentive calculation contract
  71 |     |     /// @param incentiveFundContract Address of the incentive fund contract
  72 |     |     struct SuperAssetData {
  73 |     |         address superAssetStrategist;
  74 |     |         address superAssetManager;
  75 |     |         address incentiveFundManager;
  76 |     |         address incentiveCalculationContract;
  77 |     |         address incentiveFundContract;
  78 |     |     }
  79 |     | 
  80 |     |     /*//////////////////////////////////////////////////////////////
  81 |     |                             EXTERNAL METHODS
  82 |     |     //////////////////////////////////////////////////////////////*/
  83 |     | 
  84 |     |     /// @notice Sets the manager for a SuperAsset
  85 |     |     /// @param superAsset Address of the SuperAsset contract
  86 |     |     /// @param _superAssetManager Address of the manager
  87 |     |     function setSuperAssetManager(address superAsset, address _superAssetManager) external;
  88 |     | 
  89 |     |     /// @notice Sets the strategist for a SuperAsset
  90 |     |     /// @param superAsset Address of the SuperAsset contract
  91 |     |     /// @param _superAssetStrategist Address of the strategist
  92 |     |     function setSuperAssetStrategist(address superAsset, address _superAssetStrategist) external;
  93 |     | 
  94 |     |     /// @notice Sets the incentive fund manager for a SuperAsset
  95 |     |     /// @param superAsset Address of the SuperAsset contract
  96 |     |     /// @param _incentiveFundManager Address of the incentive fund manager
  97 |     |     function setIncentiveFundManager(address superAsset, address _incentiveFundManager) external;
  98 |     | 
  99 |     |     /// @notice Sets the incentive calculation contract for a SuperAsset
 100 |     |     /// @param superAsset Address of the SuperAsset contract
 101 |     |     /// @param incentiveCalculationContract Address of the incentive calculation contract
 102 |     |     function setIncentiveCalculationContract(address superAsset, address incentiveCalculationContract) external;
 103 |     | 
 104 |     |     /// @notice Gets the manager for a SuperAsset
 105 |     |     /// @param superAsset Address of the SuperAsset contract
 106 |     |     /// @return superAssetManager Address of the manager
 107 |     |     function getSuperAssetManager(address superAsset) external view returns (address);
 108 |     | 
 109 |     |     /// @notice Gets the strategist for a SuperAsset
 110 |     |     /// @param superAsset Address of the SuperAsset contract
 111 |     |     /// @return superAssetStrategist Address of the strategist
 112 |     |     function getSuperAssetStrategist(address superAsset) external view returns (address);
 113 |     | 
 114 |     |     /// @notice Gets the incentive fund manager for a SuperAsset
 115 |     |     /// @param superAsset Address of the SuperAsset contract
 116 |     |     /// @return incentiveFundManager Address of the incentive fund manager
 117 |     |     function getIncentiveFundManager(address superAsset) external view returns (address);
 118 |     | 
 119 |     |     /// @notice Gets the incentive calculation contract for a SuperAsset
 120 |     |     /// @param superAsset Address of the SuperAsset contract
 121 |     |     /// @return incentiveCalculationContract Address of the incentive calculation contract
 122 |     |     function getIncentiveCalculationContract(address superAsset) external view returns (address);
 123 |     | 
 124 |     |     /// @notice Gets the incentive fund contract for a SuperAsset
 125 |     |     /// @param superAsset Address of the SuperAsset contract
 126 |     |     /// @return incentiveFundContract Address of the incentive fund contract
 127 |     |     function getIncentiveFundContract(address superAsset) external view returns (address);
 128 |     | 
 129 |     |     /// @notice Adds an Incentive Calculation Contract to the whitelist
 130 |     |     /// @param icc Address of the Incentive Calculation Contract
 131 |     |     function addICCToWhitelist(address icc) external;
 132 |     | 
 133 |     |     /// @notice Removes an Incentive Calculation Contract from the whitelist
 134 |     |     /// @param icc Address of the Incentive Calculation Contract
 135 |     |     function removeICCFromWhitelist(address icc) external;
 136 |     | 
 137 |     |     /// @notice Checks if an Incentive Calculation Contract is whitelisted
 138 |     |     /// @param icc Address of the Incentive Calculation Contract
 139 |     |     /// @return isValid Whether the Incentive Calculation Contract is whitelisted
 140 |     |     function isICCWhitelisted(address icc) external view returns (bool);
 141 |     | 
 142 |     |     /// @notice Creates a new SuperAsset instance with its dependencies
 143 |     |     /// @param params Parameters for creating the SuperAsset
 144 |     |     /// @return superAsset Address of the deployed SuperAsset contract
 145 |     |     /// @return incentiveFund Address of the deployed IncentiveFundContract
 146 |     |     function createSuperAsset(AssetCreationParams calldata params)
 147 |     |         external
 148 |     |         returns (address superAsset, address incentiveFund);
 149 |     | }
 150 |     | 

/opt/scfuzzbench/work/target/src/interfaces/SuperVault/ISuperVault.sol
  1 |     | // SPDX-License-Identifier: UNLICENSED
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | /// @title ISuperVault
  5 |     | /// @notice Interface for SuperVault core contract that manages share minting
  6 |     | /// @author Superform Labs
  7 |     | interface ISuperVault {
  8 |     |     /*//////////////////////////////////////////////////////////////
  9 |     |                                 ERRORS
 10 |     |     //////////////////////////////////////////////////////////////*/
 11 |     |     error INVALID_ASSET();
 12 |     |     error INVALID_STRATEGY();
 13 |     |     error INVALID_ESCROW();
 14 |     |     error ZERO_ADDRESS();
 15 |     |     error ZERO_AMOUNT();
 16 |     |     error INVALID_OWNER_OR_OPERATOR();
 17 |     |     error INVALID_AMOUNT();
 18 |     |     error REQUEST_NOT_FOUND();
 19 |     |     error UNAUTHORIZED();
 20 |     |     error DEADLINE_PASSED();
 21 |     |     error INVALID_SIGNATURE();
 22 |     |     error NOT_IMPLEMENTED();
 23 |     |     error INVALID_NONCE();
 24 |     |     error INVALID_WITHDRAW_PRICE();
 25 |     |     error TRANSFER_FAILED();
 26 |     |     error CAP_EXCEEDED();
 27 |     |     error INVALID_PPS();
 28 |     |     error INVALID_CONTROLLER();
 29 |     |     error CONTROLLER_MUST_EQUAL_OWNER();
 30 |     | 
 31 |     |     /*//////////////////////////////////////////////////////////////
 32 |     |                                 EVENTS
 33 |     |     //////////////////////////////////////////////////////////////*/
 34 |     | 
 35 |     |     event RedeemClaimable(
 36 |     |         address indexed user,
 37 |     |         uint256 indexed requestId,
 38 |     |         uint256 assets,
 39 |     |         uint256 shares,
 40 |     |         uint256 averageWithdrawPrice,
 41 |     |         uint256 accumulatorShares,
 42 |     |         uint256 accumulatorCostBasis
 43 |     |     );
 44 |     | 
 45 |     |     event NonceInvalidated(address indexed sender, bytes32 indexed nonce);
 46 |     | 
 47 |     |     event RedeemRequestCancelled(address indexed controller, address indexed sender);
 48 |     | 
 49 |     |     event SuperGovernorSet(address indexed superGovernor);
 50 |     | 
 51 |     |     /*//////////////////////////////////////////////////////////////
 52 |     |                             EXTERNAL METHODS
 53 |     |     //////////////////////////////////////////////////////////////*/
 54 |     | 
 55 |     |     function cancelRedeem(address controller) external;
 56 |     | 
 57 |     |     /// @notice Burn shares, only callable by strategy
 58 |     |     /// @param amount The amount of shares to burn
 59 |     |     function burnShares(uint256 amount) external;
 60 |     | 
 61 |     |     /// @notice Callback function for when a redeem becomes claimable
 62 |     |     /// @param user The user whose redeem is claimable
 63 |     |     /// @param assets The amount of assets to be received
 64 |     |     /// @param shares The amount of shares redeemed
 65 |     |     /// @param averageWithdrawPrice The average price of the redeem
 66 |     |     /// @param accumulatorShares The amount of shares in the accumulator
 67 |     |     /// @param accumulatorCostBasis The cost basis of the accumulator
 68 |     |     function onRedeemClaimable(
 69 |     |         address user,
 70 |     |         uint256 assets,
 71 |     |         uint256 shares,
 72 |     |         uint256 averageWithdrawPrice,
 73 |     |         uint256 accumulatorShares,
 74 |     |         uint256 accumulatorCostBasis
 75 |     |     )
 76 |     |         external;
 77 |     | }
 78 |     | 

/opt/scfuzzbench/work/target/src/interfaces/SuperVault/ISuperVaultAggregator.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
   5 |     | import { ISuperVaultStrategy } from "../SuperVault/ISuperVaultStrategy.sol";
   6 |     | 
   7 |     | /// @title ISuperVaultAggregator
   8 |     | /// @author Superform Labs
   9 |     | /// @notice Interface for the SuperVaultAggregator contract
  10 |     | /// @dev Registry and PPS oracle for all SuperVaults
  11 |     | interface ISuperVaultAggregator {
  12 |     |     /*//////////////////////////////////////////////////////////////
  13 |     |                                  STRUCTS
  14 |     |     //////////////////////////////////////////////////////////////*/
  15 |     |     /// @notice Arguments for forwarding PPS updates to avoid stack too deep errors
  16 |     |     /// @param strategy Address of the strategy being updated
  17 |     |     /// @param isExempt Whether the update is exempt from paying upkeep
  18 |     |     /// @param pps New price-per-share value
  19 |     |     /// @param ppsStdev Standard deviation of the price-per-share
  20 |     |     /// @param validatorSet Number of validators who calculated this PPS
  21 |     |     /// @param totalValidators Total number of validators in the network
  22 |     |     /// @param timestamp Timestamp when the value was generated
  23 |     |     /// @param upkeepCost Amount of upkeep tokens to charge if not exempt
  24 |     |     struct PPSUpdateData {
  25 |     |         address strategy;
  26 |     |         bool isExempt;
  27 |     |         uint256 pps;
  28 |     |         uint256 ppsStdev;
  29 |     |         uint256 validatorSet;
  30 |     |         uint256 totalValidators;
  31 |     |         uint256 timestamp;
  32 |     |         uint256 upkeepCost;
  33 |     |     }
  34 |     | 
  35 |     |     /// @notice Local variables for vault creation to avoid stack too deep
  36 |     |     /// @param currentNonce Current vault creation nonce
  37 |     |     /// @param salt Salt for deterministic proxy creation
  38 |     |     /// @param success Whether asset decimals retrieval was successful
  39 |     |     /// @param assetDecimals Decimals of the underlying asset
  40 |     |     /// @param underlyingDecimals Final decimals to use (18 if retrieval failed)
  41 |     |     /// @param initialPPS Initial price-per-share value
  42 |     |     struct VaultCreationLocalVars {
  43 |     |         uint256 currentNonce;
  44 |     |         bytes32 salt;
  45 |     |         bool success;
  46 |     |         uint8 assetDecimals;
  47 |     |         uint8 underlyingDecimals;
  48 |     |         uint256 initialPPS;
  49 |     |     }
  50 |     | 
  51 |     |     /// @notice Strategy configuration and state data
  52 |     |     /// @param pps Current price-per-share value
  53 |     |     /// @param lastUpdateTimestamp Last time PPS was updated
  54 |     |     /// @param minUpdateInterval Minimum time interval between PPS updates
  55 |     |     /// @param maxStaleness Maximum time allowed between PPS updates before staleness
  56 |     |     /// @param isPaused Whether the strategy is paused
  57 |     |     /// @param mainManager Address of the primary manager controlling the strategy
  58 |     |     /// @param secondaryManagers Set of secondary managers that can manage the strategy
  59 |     |     /// @param authorizedCallers List of callers authorized to update PPS without paying upkeep
  60 |     |     struct StrategyData {
  61 |     |         uint256 pps;
  62 |     |         uint256 ppsStdev;
  63 |     |         uint256 lastUpdateTimestamp;
  64 |     |         uint256 minUpdateInterval;
  65 |     |         uint256 maxStaleness;
  66 |     |         bool isPaused;
  67 |     |         address mainManager;
  68 |     |         EnumerableSet.AddressSet secondaryManagers;
  69 |     |         EnumerableSet.AddressSet authorizedCallers;
  70 |     |         // Manager change proposal data
  71 |     |         address proposedManager;
  72 |     |         uint256 managerChangeEffectiveTime;
  73 |     |         // Hook validation data
  74 |     |         bytes32 managerHooksRoot;
  75 |     |         // Hook root update proposal data
  76 |     |         bytes32 proposedHooksRoot;
  77 |     |         uint256 hooksRootEffectiveTime;
  78 |     |         // Veto status
  79 |     |         bool hooksRootVetoed;
  80 |     |         // PPS Verification thresholds
  81 |     |         uint256 dispersionThreshold; // Threshold for standard deviation / mean
  82 |     |         uint256 deviationThreshold; // Threshold for abs(new - current) / current
  83 |     |         uint256 mnThreshold; // Threshold for validatorSet / totalValidators ratio, scaled by 1e18
  84 |     |         // Banned global leaves mapping
  85 |     |         mapping(bytes32 => bool) bannedLeaves; // Mapping of leaf hash to banned status
  86 |     |     }
  87 |     | 
  88 |     |     /// @notice Parameters for creating a new SuperVault trio
  89 |     |     /// @param asset Address of the underlying asset
  90 |     |     /// @param name Name of the vault token
  91 |     |     /// @param symbol Symbol of the vault token
  92 |     |     /// @param mainManager Address of the vault mainManager
  93 |     |     /// @param minUpdateInterval Minimum time interval between PPS updates
  94 |     |     /// @param maxStaleness Maximum time allowed between PPS updates before staleness
  95 |     |     /// @param feeConfig Fee configuration for the vault
  96 |     |     struct VaultCreationParams {
  97 |     |         address asset;
  98 |     |         string name;
  99 |     |         string symbol;
 100 |     |         address mainManager;
 101 |     |         address[] secondaryManagers;
 102 |     |         uint256 minUpdateInterval;
 103 |     |         uint256 maxStaleness;
 104 |     |         ISuperVaultStrategy.FeeConfig feeConfig;
 105 |     |     }
 106 |     | 
 107 |     |     /// @notice Struct to hold cached hook validation state variables to avoid stack too deep
 108 |     |     /// @param globalHooksRootVetoed Cached global hooks root veto status
 109 |     |     /// @param globalHooksRoot Cached global hooks root
 110 |     |     /// @param strategyHooksRootVetoed Cached strategy hooks root veto status
 111 |     |     /// @param strategyRoot Cached strategy hooks root
 112 |     |     struct HookValidationCache {
 113 |     |         bool globalHooksRootVetoed;
 114 |     |         bytes32 globalHooksRoot;
 115 |     |         bool strategyHooksRootVetoed;
 116 |     |         bytes32 strategyRoot;
 117 |     |     }
 118 |     | 
 119 |     |     /// @notice Arguments for validating a hook to avoid stack too deep
 120 |     |     /// @param hookAddress Address of the hook contract
 121 |     |     /// @param hookArgs Encoded arguments for the hook operation
 122 |     |     /// @param globalProof Merkle proof for the global root
 123 |     |     /// @param strategyProof Merkle proof for the strategy-specific root
 124 |     |     struct ValidateHookArgs {
 125 |     |         address hookAddress;
 126 |     |         bytes hookArgs;
 127 |     |         bytes32[] globalProof;
 128 |     |         bytes32[] strategyProof;
 129 |     |     }
 130 |     | 
 131 |     |     /*//////////////////////////////////////////////////////////////
 132 |     |                                  EVENTS
 133 |     |     //////////////////////////////////////////////////////////////*/
 134 |     |     /// @notice Emitted when a new vault trio is created
 135 |     |     /// @param vault Address of the created SuperVault
 136 |     |     /// @param strategy Address of the created SuperVaultStrategy
 137 |     |     /// @param escrow Address of the created SuperVaultEscrow
 138 |     |     /// @param asset Address of the underlying asset
 139 |     |     /// @param name Name of the vault token
 140 |     |     /// @param symbol Symbol of the vault token
 141 |     |     /// @param nonce The nonce used for vault creation
 142 |     |     event VaultDeployed(
 143 |     |         address indexed vault,
 144 |     |         address indexed strategy,
 145 |     |         address escrow,
 146 |     |         address asset,
 147 |     |         string name,
 148 |     |         string symbol,
 149 |     |         uint256 indexed nonce
 150 |     |     );
 151 |     | 
 152 |     |     /// @notice Emitted when a PPS value is updated
 153 |     |     /// @param strategy Address of the strategy
 154 |     |     /// @param pps New price-per-share value
 155 |     |     /// @param ppsStdev Standard deviation of price-per-share value
 156 |     |     /// @param validatorSet Number of validators who calculated this PPS
 157 |     |     /// @param totalValidators Total number of validators in the network
 158 |     |     /// @param timestamp Timestamp of the update
 159 |     |     event PPSUpdated(
 160 |     |         address indexed strategy,
 161 |     |         uint256 pps,
 162 |     |         uint256 ppsStdev,
 163 |     |         uint256 validatorSet,
 164 |     |         uint256 totalValidators,
 165 |     |         uint256 timestamp
 166 |     |     );
 167 |     | 
 168 |     |     /// @notice Emitted when a strategy is paused due to missed updates
 169 |     |     /// @param strategy Address of the paused strategy
 170 |     |     event StrategyPaused(address indexed strategy);
 171 |     | 
 172 |     |     /// @notice Emitted when a strategy is unpaused
 173 |     |     /// @param strategy Address of the unpaused strategy
 174 |     |     event StrategyUnpaused(address indexed strategy);
 175 |     | 
 176 |     |     /// @notice Emitted when a strategy validation check fails but execution continues
 177 |     |     /// @param strategy Address of the strategy that failed the check
 178 |     |     /// @param reason String description of which check failed
 179 |     |     event StrategyCheckFailed(address indexed strategy, string reason);
 180 |     | 
 181 |     |     /// @notice Emitted when upkeep tokens are deposited
 182 |     |     /// @param manager Address of the manager
 183 |     |     /// @param amount Amount of UP tokens deposited
 184 |     |     event UpkeepDeposited(address indexed manager, uint256 amount);
 185 |     | 
 186 |     |     /// @notice Emitted when upkeep tokens are withdrawn
 187 |     |     /// @param manager Address of the manager
 188 |     |     /// @param amount Amount of UP tokens withdrawn
 189 |     |     event UpkeepWithdrawn(address indexed manager, uint256 amount);
 190 |     | 
 191 |     |     /// @notice Emitted when upkeep tokens are spent for validation
 192 |     |     /// @param manager Address of the manager
 193 |     |     /// @param amount Amount of UP tokens spent
 194 |     |     event UpkeepSpent(address indexed manager, uint256 amount);
 195 |     | 
 196 |     |     /// @notice Emitted when stake tokens are deposited
 197 |     |     /// @param manager Address of the manager
 198 |     |     /// @param amount Amount of UP tokens deposited as stake
 199 |     |     event StakeDeposited(address indexed manager, uint256 amount);
 200 |     | 
 201 |     |     /// @notice Emitted when stake tokens are withdrawn
 202 |     |     /// @param manager Address of the manager
 203 |     |     /// @param amount Amount of UP tokens withdrawn from stake
 204 |     |     event StakeWithdrawn(address indexed manager, uint256 amount);
 205 |     | 
 206 |     |     /// @notice Emitted when a manager's stake is slashed
 207 |     |     /// @param manager The manager whose stake was slashed
 208 |     |     /// @param amount The amount of UP tokens slashed
 209 |     |     event StakeSlashed(address indexed manager, uint256 amount);
 210 |     | 
 211 |     |     /// @notice Emitted when an authorized caller is added for a strategy
 212 |     |     /// @param strategy Address of the strategy
 213 |     |     /// @param caller Address of the authorized caller
 214 |     |     event AuthorizedCallerAdded(address indexed strategy, address indexed caller);
 215 |     | 
 216 |     |     /// @notice Emitted when an authorized caller is removed for a strategy
 217 |     |     /// @param strategy Address of the strategy
 218 |     |     /// @param caller Address of the removed caller
 219 |     |     event AuthorizedCallerRemoved(address indexed strategy, address indexed caller);
 220 |     | 
 221 |     |     /// @notice Emitted when a secondary manager is added to a strategy
 222 |     |     /// @param strategy Address of the strategy
 223 |     |     /// @param manager Address of the manager added
 224 |     |     event SecondaryManagerAdded(address indexed strategy, address indexed manager);
 225 |     | 
 226 |     |     /// @notice Emitted when a secondary manager is removed from a strategy
 227 |     |     /// @param strategy Address of the strategy
 228 |     |     /// @param manager Address of the manager removed
 229 |     |     event SecondaryManagerRemoved(address indexed strategy, address indexed manager);
 230 |     | 
 231 |     |     /// @notice Emitted when a primary manager is changed
 232 |     |     /// @param strategy Address of the strategy
 233 |     |     /// @param oldManager Address of the old primary manager
 234 |     |     /// @param newManager Address of the new primary manager
 235 |     |     event PrimaryManagerChanged(
 236 |     |         address indexed strategy, address indexed oldManager, address indexed newManager
 237 |     |     );
 238 |     | 
 239 |     |     /// @notice Emitted when a primary manager is changed to a superform manager
 240 |     |     /// @param strategy Address of the strategy
 241 |     |     /// @param oldManager Address of the old primary manager
 242 |     |     /// @param newManager Address of the new primary manager (superform manager)
 243 |     |     event PrimaryManagerChangedToSuperform(
 244 |     |         address indexed strategy, address indexed oldManager, address indexed newManager
 245 |     |     );
 246 |     | 
 247 |     |     /// @notice Emitted when a change to primary manager is proposed by a secondary manager
 248 |     |     /// @param strategy Address of the strategy
 249 |     |     /// @param proposer Address of the secondary manager who made the proposal
 250 |     |     /// @param newManager Address of the proposed new primary manager
 251 |     |     /// @param effectiveTime Timestamp when the proposal can be executed
 252 |     |     event PrimaryManagerChangeProposed(
 253 |     |         address indexed strategy, address indexed proposer, address indexed newManager, uint256 effectiveTime
 254 |     |     );
 255 |     | 
 256 |     |     /// @notice Emitted when a PPS update is stale (Validators could get slashed for innactivity)
 257 |     |     /// @param strategy Address of the strategy
 258 |     |     /// @param updateAuthority Address of the update authority
 259 |     |     /// @param timestamp Timestamp of the stale update
 260 |     |     event StaleUpdate(address indexed strategy, address indexed updateAuthority, uint256 timestamp);
 261 |     | 
 262 |     |     /// @notice Emitted when the upkeep cost per update is changed
 263 |     |     /// @param oldCost Previous upkeep cost per update
 264 |     |     /// @param newCost New upkeep cost per update
 265 |     |     event UpkeepCostUpdated(uint256 oldCost, uint256 newCost);
 266 |     | 
 267 |     |     /// @notice Emitted when the global hooks Merkle root is being updated
 268 |     |     /// @param root New root value
 269 |     |     /// @param effectiveTime Timestamp when the root becomes effective
 270 |     |     event GlobalHooksRootUpdateProposed(bytes32 indexed root, uint256 effectiveTime);
 271 |     | 
 272 |     |     /// @notice Emitted when the global hooks Merkle root is updated
 273 |     |     /// @param oldRoot Previous root value
 274 |     |     /// @param newRoot New root value
 275 |     |     event GlobalHooksRootUpdated(bytes32 indexed oldRoot, bytes32 newRoot);
 276 |     | 
 277 |     |     /// @notice Emitted when a strategy-specific hooks Merkle root is updated
 278 |     |     /// @param strategy Address of the strategy
 279 |     |     /// @param oldRoot Previous root value (may be zero)
 280 |     |     /// @param newRoot New root value
 281 |     |     event StrategyHooksRootUpdated(address indexed strategy, bytes32 oldRoot, bytes32 newRoot);
 282 |     | 
 283 |     |     /// @notice Emitted when a strategy-specific hooks Merkle root is proposed
 284 |     |     /// @param strategy Address of the strategy
 285 |     |     /// @param proposer Address of the account proposing the new root
 286 |     |     /// @param root New root value
 287 |     |     /// @param effectiveTime Timestamp when the root becomes effective
 288 |     |     event StrategyHooksRootUpdateProposed(
 289 |     |         address indexed strategy, address indexed proposer, bytes32 root, uint256 effectiveTime
 290 |     |     );
 291 |     | 
 292 |     |     /// @notice Emitted when a proposed global hooks root update is vetoed by SuperGovernor
 293 |     |     /// @param vetoed Whether the root is being vetoed (true) or unvetoed (false)
 294 |     |     /// @param root The root value affected
 295 |     |     event GlobalHooksRootVetoStatusChanged(bool vetoed, bytes32 indexed root);
 296 |     | 
 297 |     |     /// @notice Emitted when a strategy's hooks Merkle root veto status changes
 298 |     |     /// @param strategy Address of the strategy
 299 |     |     /// @param vetoed Whether the root is being vetoed (true) or unvetoed (false)
 300 |     |     /// @param root The root value affected
 301 |     |     event StrategyHooksRootVetoStatusChanged(address indexed strategy, bool vetoed, bytes32 indexed root);
 302 |     | 
 303 |     |     /// @notice Emitted when a strategy's PPS verification thresholds are updated
 304 |     |     /// @param strategy Address of the strategy
 305 |     |     /// @param dispersionThreshold New dispersion threshold (stddev/mean)
 306 |     |     /// @param deviationThreshold New deviation threshold (abs diff/current)
 307 |     |     /// @param mnThreshold New M/N threshold (validatorSet/totalValidators)
 308 |     |     event PPSVerificationThresholdsUpdated(
 309 |     |         address indexed strategy, uint256 dispersionThreshold, uint256 deviationThreshold, uint256 mnThreshold
 310 |     |     );
 311 |     | 
 312 |     |     /// @notice Emitted when the hooks root update timelock is changed
 313 |     |     /// @param newTimelock New timelock duration in seconds
 314 |     |     event HooksRootUpdateTimelockChanged(uint256 newTimelock);
 315 |     | 
 316 |     |     /// @notice Emitted when global leaves status is changed for a strategy
 317 |     |     /// @param strategy Address of the strategy
 318 |     |     /// @param leaves Array of leaf hashes that had their status changed
 319 |     |     /// @param statuses Array of new banned statuses (true = banned, false = allowed)
 320 |     |     event GlobalLeavesStatusChanged(address indexed strategy, bytes32[] leaves, bool[] statuses);
 321 |     | 
 322 |     |     /// @notice Emitted when a proposed global hooks root update is vetoed by a guardian
 323 |     |     /// @param guardian Address of the guardian who vetoed the update
 324 |     |     /// @param root The vetoed root value
 325 |     |     event GlobalHooksRootVetoed(address indexed guardian, bytes32 indexed root);
 326 |     | 
 327 |     |     /// @notice Emitted when a proposed strategy hooks root update is vetoed by a guardian
 328 |     |     /// @param guardian Address of the guardian who vetoed the update
 329 |     |     /// @param strategy Address of the strategy whose root update was vetoed
 330 |     |     /// @param root The vetoed root value
 331 |     |     event StrategyHooksRootVetoed(address indexed guardian, address indexed strategy, bytes32 indexed root);
 332 |     | 
 333 |     |     /// @notice Emitted when upkeep is claimed
 334 |     |     /// @param superBank Address of the superBank
 335 |     |     /// @param amount Amount of upkeep claimed
 336 |     |     event UpkeepClaimed(address indexed superBank, uint256 amount);
 337 |     | 
 338 |     |     /// @notice Emitted when PPS update is too frequent (before minUpdateInterval)
 339 |     |     event UpdateTooFrequent();
 340 |     | 
 341 |     |     /// @notice Emitted when PPS update timestamp is not monotonically increasing
 342 |     |     event TimestampNotMonotonic();
 343 |     | 
 344 |     |     /// @notice Emitted when a manager does not have enough upkeep balance
 345 |     |     event InsufficientUpkeep(address indexed strategy, address indexed manager, uint256 balance, uint256 cost);
 346 |     | 
 347 |     |     /// @notice Emitted when the provided timestamp is too large
 348 |     |     event ProvidedTimestampExceedsBlockTimestamp(address indexed strategy, uint256 argsTimestamp, uint256 blockTimestamp);
 349 |     | 
 350 |     |     /// @notice Emitted when a strategy is unknown
 351 |     |     event UnknownStrategy(address indexed strategy);
 352 |     | 
 353 |     |     /// @notice Emitted when a strategy is managed by Superform
 354 |     |     event SuperformManager(address indexed strategy, address indexed manager);
 355 |     | 
 356 |     |     /// @notice Emitted when the caller is authorized
 357 |     |     event AuthorizedCaller(address indexed strategy, address indexed caller);
 358 |     | 
 359 |     |     /*///////////////////////////////////////////////////////////////
 360 |     |                                  ERRORS
 361 |     |     //////////////////////////////////////////////////////////////*/
 362 |     |     /// @notice Thrown when address provided is zero
 363 |     |     error ZERO_ADDRESS();
 364 |     |     /// @notice Thrown when amount provided is zero
 365 |     |     error ZERO_AMOUNT();
 366 |     |     /// @notice Thrown when array length is zero
 367 |     |     error ZERO_ARRAY_LENGTH();
 368 |     |     /// @notice Thrown when array length is zero
 369 |     |     error ARRAY_LENGTH_MISMATCH();
 370 |     |     /// @notice Thrown when asset is invalid
 371 |     |     error INVALID_ASSET();
 372 |     |     /// @notice Thrown when insufficient upkeep balance for operation
 373 |     |     error INSUFFICIENT_UPKEEP();
 374 |     |     /// @notice Thrown when vault is paused but operation requires active state
 375 |     |     error VAULT_PAUSED();
 376 |     |     /// @notice Thrown when caller is not an approved PPS oracle
 377 |     |     error UNAUTHORIZED_PPS_ORACLE();
 378 |     |     /// @notice Thrown when PPS update is too stale (after maxStaleness)
 379 |     |     error UPDATE_TOO_STALE();
 380 |     |     /// @notice Thrown when caller is not authorized for update
 381 |     |     error UNAUTHORIZED_UPDATE_AUTHORITY();
 382 |     |     /// @notice Thrown when strategy address is not a known SuperVault strategy
 383 |     |     error UNKNOWN_STRATEGY();
 384 |     |     /// @notice Thrown when withdrawing more upkeep than available
 385 |     |     error INSUFFICIENT_UPKEEP_BALANCE();
 386 |     |     /// @notice Thrown when withdrawing more stake than available
 387 |     |     error INSUFFICIENT_STAKE_BALANCE();
 388 |     |     /// @notice Thrown when caller is already authorized
 389 |     |     error CALLER_ALREADY_AUTHORIZED();
 390 |     |     /// @notice Thrown when caller is not authorized
 391 |     |     error CALLER_NOT_AUTHORIZED();
 392 |     |     /// @notice Thrown when array index is out of bounds
 393 |     |     error INDEX_OUT_OF_BOUNDS();
 394 |     |     /// @notice Thrown when attempting to remove the last manager
 395 |     |     error CANNOT_REMOVE_LAST_MANAGER();
 396 |     |     /// @notice Thrown when attempting to add a manager that already exists
 397 |     |     error MANAGER_ALREADY_EXISTS();
 398 |     |     /// @notice Thrown when there is no pending global hooks root change
 399 |     |     error NO_PENDING_GLOBAL_ROOT_CHANGE();
 400 |     |     /// @notice Thrown when attempting to execute an in-progress manager change before timelock elapsed
 401 |     |     error MANAGER_CHANGE_NOT_READY();
 402 |     |     /// @notice Thrown when attempting to execute a hooks root change before timelock has elapsed
 403 |     |     error ROOT_UPDATE_NOT_READY();
 404 |     |     /// @notice Thrown when a provided hook fails Merkle proof validation
 405 |     |     error HOOK_VALIDATION_FAILED();
 406 |     |     /// @notice Thrown when a non-guardian tries to veto a root update
 407 |     |     error NOT_A_GUARDIAN();
 408 |     |     /// @notice Thrown when trying to veto a root update that doesn't exist
 409 |     |     error NO_PENDING_ROOT_UPDATE();
 410 |     |     /// @notice Thrown when manager is not found
 411 |     |     error MANAGER_NOT_FOUND();
 412 |     |     /// @notice Thrown when there is no pending manager change proposal
 413 |     |     error NO_PENDING_MANAGER_CHANGE();
 414 |     |     /// @notice Thrown when caller is not authorized to update settings
 415 |     |     error UNAUTHORIZED_CALLER();
 416 |     |     /// @notice Thrown when the timelock for a proposed change has not expired
 417 |     |     error TIMELOCK_NOT_EXPIRED();
 418 |     |     /// @notice Thrown when an array length is invalid
 419 |     |     error INVALID_ARRAY_LENGTH();
 420 |     |     /// @notice Thrown when trying to add a protected keeper as an authorized caller
 421 |     |     error CANNOT_ADD_PROTECTED_KEEPER();
 422 |     |     /// @notice Thrown when the provided maxStaleness is less than the minimum required staleness
 423 |     |     error MAX_STALENESS_TOO_LOW();
 424 |     |     /// @notice Thrown when arrays have mismatched lengths
 425 |     |     error MISMATCHED_ARRAY_LENGTHS();
 426 |     |     /// @notice Thrown when timestamp is invalid
 427 |     |     error INVALID_TIMESTAMP(uint256 index);
 428 |     |     /// @notice Thrown when too many secondary managers are added
 429 |     |     error TOO_MANY_SECONDARY_MANAGERS();
 430 |     |     /// @notice Thrown when the number of strategies exceeds the maximum allowed
 431 |     |     error MAX_STRATEGIES_EXCEEDED();
 432 |     |     /// @notice Thrown when provided timestamp is too large
 433 |     |     error TIMESTAMP_EXCEEDS_BLOCK();
 434 |     | 
 435 |     |     /*//////////////////////////////////////////////////////////////
 436 |     |                             VAULT CREATION
 437 |     |     //////////////////////////////////////////////////////////////*/
 438 |     |     /// @notice Creates a new SuperVault trio (SuperVault, SuperVaultStrategy, SuperVaultEscrow)
 439 |     |     /// @param params Parameters for the new vault creation
 440 |     |     /// @return superVault Address of the created SuperVault
 441 |     |     /// @return strategy Address of the created SuperVaultStrategy
 442 |     |     /// @return escrow Address of the created SuperVaultEscrow
 443 |     |     function createVault(VaultCreationParams calldata params)
 444 |     |         external
 445 |     |         returns (address superVault, address strategy, address escrow);
 446 |     | 
 447 |     |     /*//////////////////////////////////////////////////////////////
 448 |     |                           PPS UPDATE FUNCTIONS
 449 |     |     //////////////////////////////////////////////////////////////*/
 450 |     |     /// @notice Arguments for batch forwarding PPS updates
 451 |     |     /// @param strategies Array of strategy addresses
 452 |     |     /// @param ppss Array of price-per-share values
 453 |     |     /// @param ppsStdevs Array of standard deviations of price-per-share values
 454 |     |     /// @param validatorSets Array of numbers of validators who calculated each PPS
 455 |     |     /// @param totalValidators Total number of validators in the network
 456 |     |     /// @param timestamps Array of timestamps when values were generated
 457 |     |     struct ForwardPPSArgs {
 458 |     |         address[] strategies;
 459 |     |         uint256[] ppss;
 460 |     |         uint256[] ppsStdevs;
 461 |     |         uint256[] validatorSets;
 462 |     |         uint256[] totalValidators;
 463 |     |         uint256[] timestamps;
 464 |     |         address updateAuthority;
 465 |     |     }
 466 |     | 
 467 |     |     /// @notice Batch forwards validated PPS updates to multiple strategies
 468 |     |     /// @param args Struct containing all batch PPS update parameters
 469 |     |     function forwardPPS(ForwardPPSArgs calldata args) external;
 470 |     | 
 471 |     |     /*//////////////////////////////////////////////////////////////
 472 |     |                         UPKEEP MANAGEMENT
 473 |     |     //////////////////////////////////////////////////////////////*/
 474 |     | 
 475 |     |     /// @notice Deposits UP tokens for manager upkeep
 476 |     |     /// @param manager Address of the manager to deposit for
 477 |     |     /// @param amount Amount of UP tokens to deposit
 478 |     |     function depositUpkeep(address manager, uint256 amount) external;
 479 |     | 
 480 |     |     /// @notice Withdraws UP tokens from manager upkeep balance
 481 |     |     /// @param amount Amount of UP tokens to withdraw
 482 |     |     function withdrawUpkeep(uint256 amount) external;
 483 |     | 
 484 |     |     /// @notice Claims upkeep tokens from the contract
 485 |     |     /// @param amount Amount of UP tokens to claim
 486 |     |     function claimUpkeep(uint256 amount) external;
 487 |     | 
 488 |     |     /*//////////////////////////////////////////////////////////////
 489 |     |                         STAKE MANAGEMENT
 490 |     |     //////////////////////////////////////////////////////////////*/
 491 |     | 
 492 |     |     /// @notice Deposits UP tokens as stake for manager economic security
 493 |     |     /// @param manager Address of the manager to deposit stake for
 494 |     |     /// @param amount Amount of UP tokens to deposit as stake
 495 |     |     function depositStake(address manager, uint256 amount) external;
 496 |     | 
 497 |     |     /// @notice Withdraws UP tokens from manager stake balance
 498 |     |     /// @param amount Amount of UP tokens to withdraw from stake
 499 |     |     function withdrawStake(uint256 amount) external;
 500 |     | 
 501 |     |     /// @notice Slashes a manager's stake balance by a specified amount
 502 |     |     /// @param manager The manager whose stake will be slashed
 503 |     |     /// @param amount The amount of UP tokens to slash from the manager's stake balance
 504 |     |     function slashStake(address manager, uint256 amount) external;
 505 |     | 
 506 |     |     /*//////////////////////////////////////////////////////////////
 507 |     |                         AUTHORIZED CALLER MANAGEMENT
 508 |     |     //////////////////////////////////////////////////////////////*/
 509 |     | 
 510 |     |     /// @notice Adds an authorized caller for a strategy
 511 |     |     /// @param strategy Address of the strategy
 512 |     |     /// @param caller Address of the caller to authorize
 513 |     |     function addAuthorizedCaller(address strategy, address caller) external;
 514 |     | 
 515 |     |     /// @notice Removes an authorized caller for a strategy
 516 |     |     /// @param strategy Address of the strategy
 517 |     |     /// @param caller Address of the caller to remove
 518 |     |     function removeAuthorizedCaller(address strategy, address caller) external;
 519 |     | 
 520 |     |     /*//////////////////////////////////////////////////////////////
 521 |     |                        MANAGER MANAGEMENT FUNCTIONS
 522 |     |     //////////////////////////////////////////////////////////////*/
 523 |     | 
 524 |     |     /// @notice Adds a secondary manager to a strategy
 525 |     |     /// @notice A manager can either be secondary or primary
 526 |     |     /// @param strategy Address of the strategy
 527 |     |     /// @param manager Address of the manager to add
 528 |     |     function addSecondaryManager(address strategy, address manager) external;
 529 |     | 
 530 |     |     /// @notice Removes a secondary manager from a strategy
 531 |     |     /// @param strategy Address of the strategy
 532 |     |     /// @param manager Address of the manager to remove
 533 |     |     function removeSecondaryManager(address strategy, address manager) external;
 534 |     | 
 535 |     |     /// @notice Changes the primary manager of a strategy immediately (only callable by SuperGovernor)
 536 |     |     /// @notice A manager can either be secondary or primary
 537 |     |     /// @param strategy Address of the strategy
 538 |     |     /// @param newManager Address of the new primary manager
 539 |     |     function changePrimaryManager(address strategy, address newManager) external;
 540 |     | 
 541 |     |     /// @notice Proposes a change to the primary manager (callable by secondary managers)
 542 |     |     /// @notice A manager can either be secondary or primary
 543 |     |     /// @param strategy Address of the strategy
 544 |     |     /// @param newManager Address of the proposed new primary manager
 545 |     |     function proposeChangePrimaryManager(address strategy, address newManager) external;
 546 |     | 
 547 |     |     /// @notice Executes a previously proposed change to the primary manager after timelock
 548 |     |     /// @param strategy Address of the strategy
 549 |     |     function executeChangePrimaryManager(address strategy) external;
 550 |     | 
 551 |     |     /*//////////////////////////////////////////////////////////////
 552 |     |                         HOOK VALIDATION FUNCTIONS
 553 |     |     //////////////////////////////////////////////////////////////*/
 554 |     |     /// @notice Sets a new hooks root update timelock duration
 555 |     |     /// @param newTimelock The new timelock duration in seconds
 556 |     |     function setHooksRootUpdateTimelock(uint256 newTimelock) external;
 557 |     | 
 558 |     |     /// @notice Proposes an update to the global hooks Merkle root
 559 |     |     /// @dev Only callable by SUPER_GOVERNOR
 560 |     |     /// @param newRoot New Merkle root for global hooks validation
 561 |     |     function proposeGlobalHooksRoot(bytes32 newRoot) external;
 562 |     | 
 563 |     |     /// @notice Executes a previously proposed global hooks root update after timelock period
 564 |     |     /// @dev Can be called by anyone after the timelock period has elapsed
 565 |     |     function executeGlobalHooksRootUpdate() external;
 566 |     | 
 567 |     |     /// @notice Proposes an update to a strategy-specific hooks Merkle root
 568 |     |     /// @dev Only callable by the main manager for the strategy
 569 |     |     /// @param strategy Address of the strategy
 570 |     |     /// @param newRoot New Merkle root for strategy-specific hooks
 571 |     |     function proposeStrategyHooksRoot(address strategy, bytes32 newRoot) external;
 572 |     | 
 573 |     |     /// @notice Executes a previously proposed strategy hooks root update after timelock period
 574 |     |     /// @dev Can be called by anyone after the timelock period has elapsed
 575 |     |     /// @param strategy Address of the strategy whose root update to execute
 576 |     |     function executeStrategyHooksRootUpdate(address strategy) external;
 577 |     | 
 578 |     |     /// @notice Set veto status for the global hooks root
 579 |     |     /// @dev Only callable by SuperGovernor
 580 |     |     /// @param vetoed Whether to veto (true) or unveto (false) the global hooks root
 581 |     |     function setGlobalHooksRootVetoStatus(bool vetoed) external;
 582 |     | 
 583 |     |     /// @notice Set veto status for a strategy-specific hooks root
 584 |     |     /// @notice Sets the veto status of a strategy's hooks Merkle root
 585 |     |     /// @param strategy Address of the strategy
 586 |     |     /// @param vetoed Whether to veto (true) or unveto (false)
 587 |     |     function setStrategyHooksRootVetoStatus(address strategy, bool vetoed) external;
 588 |     | 
 589 |     |     /// @notice Updates the PPS verification thresholds for a strategy
 590 |     |     /// @param strategy Address of the strategy
 591 |     |     /// @param dispersionThreshold_ New dispersion threshold (stddev/mean ratio, scaled by 1e18)
 592 |     |     /// @param deviationThreshold_ New deviation threshold (abs diff/current ratio, scaled by 1e18)
 593 |     |     /// @param mnThreshold_ New M/N threshold (validatorSet/totalValidators ratio, scaled by 1e18)
 594 |     |     function updatePPSVerificationThresholds(
 595 |     |         address strategy,
 596 |     |         uint256 dispersionThreshold_,
 597 |     |         uint256 deviationThreshold_,
 598 |     |         uint256 mnThreshold_
 599 |     |     )
 600 |     |         external;
 601 |     | 
 602 |     |     /// @notice Changes the banned status of global leaves for a specific strategy
 603 |     |     /// @dev Only callable by the primary manager of the strategy
 604 |     |     /// @param leaves Array of leaf hashes to change status for
 605 |     |     /// @param statuses Array of banned statuses (true = banned, false = allowed)
 606 |     |     /// @param strategy Address of the strategy to change banned leaves for
 607 |     |     function changeGlobalLeavesStatus(
 608 |     |         bytes32[] memory leaves,
 609 |     |         bool[] memory statuses,
 610 |     |         address strategy
 611 |     |     )
 612 |     |         external;
 613 |     | 
 614 |     |     /*//////////////////////////////////////////////////////////////
 615 |     |                               VIEW FUNCTIONS
 616 |     |     //////////////////////////////////////////////////////////////*/
 617 |     | 
 618 |     |     /// @notice Returns the current vault creation nonce
 619 |     |     /// @dev This nonce is incremented every time a new vault is created
 620 |     |     /// @return Current vault creation nonce
 621 |     |     function getCurrentNonce() external view returns (uint256);
 622 |     | 
 623 |     |     /// @notice Check if the global hooks root is currently vetoed
 624 |     |     /// @return vetoed True if the global hooks root is vetoed
 625 |     |     function isGlobalHooksRootVetoed() external view returns (bool vetoed);
 626 |     | 
 627 |     |     /// @notice Check if a strategy hooks root is currently vetoed
 628 |     |     /// @param strategy Address of the strategy to check
 629 |     |     /// @return vetoed True if the strategy hooks root is vetoed
 630 |     |     function isStrategyHooksRootVetoed(address strategy) external view returns (bool vetoed);
 631 |     | 
 632 |     |     /// @notice Gets the current hooks root update timelock duration
 633 |     |     /// @return The current timelock duration in seconds
 634 |     |     function getHooksRootUpdateTimelock() external view returns (uint256);
 635 |     | 
 636 |     |     /// @notice Gets the current PPS (price-per-share) for a strategy
 637 |     |     /// @param strategy Address of the strategy
 638 |     |     /// @return pps Current price-per-share value
 639 |     |     function getPPS(address strategy) external view returns (uint256 pps);
 640 |     | 
 641 |     |     /// @notice Gets the current PPS and its standard deviation for a strategy
 642 |     |     /// @param strategy Address of the strategy
 643 |     |     /// @return pps Current price-per-share value
 644 |     |     /// @return ppsStdev Standard deviation of price-per-share value
 645 |     |     function getPPSWithStdDev(address strategy) external view returns (uint256 pps, uint256 ppsStdev);
 646 |     | 
 647 |     |     /// @notice Gets the last update timestamp for a strategy's PPS
 648 |     |     /// @param strategy Address of the strategy
 649 |     |     /// @return timestamp Last update timestamp
 650 |     |     function getLastUpdateTimestamp(address strategy) external view returns (uint256 timestamp);
 651 |     | 
 652 |     |     /// @notice Gets the minimum update interval for a strategy
 653 |     |     /// @param strategy Address of the strategy
 654 |     |     /// @return interval Minimum time between updates
 655 |     |     function getMinUpdateInterval(address strategy) external view returns (uint256 interval);
 656 |     | 
 657 |     |     /// @notice Gets the maximum staleness period for a strategy
 658 |     |     /// @param strategy Address of the strategy
 659 |     |     /// @return staleness Maximum time allowed between updates
 660 |     |     function getMaxStaleness(address strategy) external view returns (uint256 staleness);
 661 |     | 
 662 |     |     /// @notice Gets the PPS verification thresholds for a strategy
 663 |     |     /// @param strategy Address of the strategy
 664 |     |     /// @return dispersionThreshold The current dispersion threshold (stddev/mean ratio, scaled by 1e18)
 665 |     |     /// @return deviationThreshold The current deviation threshold (abs diff/current ratio, scaled by 1e18)
 666 |     |     /// @return mnThreshold The current M/N threshold (validatorSet/totalValidators ratio, scaled by 1e18)
 667 |     |     function getPPSVerificationThresholds(address strategy)
 668 |     |         external
 669 |     |         view
 670 |     |         returns (uint256 dispersionThreshold, uint256 deviationThreshold, uint256 mnThreshold);
 671 |     | 
 672 |     |     /// @notice Checks if a strategy is currently paused
 673 |     |     /// @param strategy Address of the strategy
 674 |     |     /// @return isPaused True if paused, false otherwise
 675 |     |     function isStrategyPaused(address strategy) external view returns (bool isPaused);
 676 |     | 
 677 |     |     /// @notice Gets the current upkeep balance for a manager
 678 |     |     /// @param manager Address of the manager
 679 |     |     /// @return balance Current upkeep balance in UP tokens
 680 |     |     function getUpkeepBalance(address manager) external view returns (uint256 balance);
 681 |     | 
 682 |     |     /// @notice Gets the current stake balance for a manager
 683 |     |     /// @param manager Address of the manager
 684 |     |     /// @return balance Current stake balance in UP tokens
 685 |     |     function getStakeBalance(address manager) external view returns (uint256 balance);
 686 |     | 
 687 |     |     /// @notice Gets all authorized callers for a strategy
 688 |     |     /// @param strategy Address of the strategy
 689 |     |     /// @return callers Array of authorized callers
 690 |     |     function getAuthorizedCallers(address strategy) external view returns (address[] memory callers);
 691 |     | 
 692 |     |     /// @notice Gets the main manager for a strategy
 693 |     |     /// @param strategy Address of the strategy
 694 |     |     /// @return manager Address of the main manager
 695 |     |     function getMainManager(address strategy) external view returns (address manager);
 696 |     | 
 697 |     |     /// @notice Checks if an address is the main manager for a strategy
 698 |     |     /// @param manager Address of the manager
 699 |     |     /// @param strategy Address of the strategy
 700 |     |     /// @return isMainManager True if the address is the main manager, false otherwise
 701 |     |     function isMainManager(address manager, address strategy) external view returns (bool isMainManager);
 702 |     | 
 703 |     |     /// @notice Gets all secondary managers for a strategy
 704 |     |     /// @param strategy Address of the strategy
 705 |     |     /// @return secondaryManagers Array of secondary manager addresses
 706 |     |     function getSecondaryManagers(address strategy) external view returns (address[] memory secondaryManagers);
 707 |     | 
 708 |     |     /// @notice Checks if an address is a secondary manager for a strategy
 709 |     |     /// @param manager Address of the manager
 710 |     |     /// @param strategy Address of the strategy
 711 |     |     /// @return isSecondaryManager True if the address is a secondary manager, false otherwise
 712 |     |     function isSecondaryManager(
 713 |     |         address manager,
 714 |     |         address strategy
 715 |     |     )
 716 |     |         external
 717 |     |         view
 718 |     |         returns (bool isSecondaryManager);
 719 |     | 
 720 |     |     /// @dev Internal helper function to check if an address is any kind of manager (primary or secondary)
 721 |     |     /// @param manager Address to check
 722 |     |     /// @param strategy The strategy to check against
 723 |     |     /// @return True if the address is either the primary manager or a secondary manager
 724 |     |     function isAnyManager(address manager, address strategy) external view returns (bool);
 725 |     | 
 726 |     |     /// @notice Gets all created SuperVaults
 727 |     |     /// @return Array of SuperVault addresses
 728 |     |     function getAllSuperVaults() external view returns (address[] memory);
 729 |     | 
 730 |     |     /// @notice Gets a SuperVault by index
 731 |     |     /// @param index The index of the SuperVault
 732 |     |     /// @return The SuperVault address at the given index
 733 |     |     function superVaults(uint256 index) external view returns (address);
 734 |     | 
 735 |     |     /// @notice Gets all created SuperVaultStrategies
 736 |     |     /// @return Array of SuperVaultStrategy addresses
 737 |     |     function getAllSuperVaultStrategies() external view returns (address[] memory);
 738 |     | 
 739 |     |     /// @notice Gets a SuperVaultStrategy by index
 740 |     |     /// @param index The index of the SuperVaultStrategy
 741 |     |     /// @return The SuperVaultStrategy address at the given index
 742 |     |     function superVaultStrategies(uint256 index) external view returns (address);
 743 |     | 
 744 |     |     /// @notice Gets all created SuperVaultEscrows
 745 |     |     /// @return Array of SuperVaultEscrow addresses
 746 |     |     function getAllSuperVaultEscrows() external view returns (address[] memory);
 747 |     | 
 748 |     |     /// @notice Gets a SuperVaultEscrow by index
 749 |     |     /// @param index The index of the SuperVaultEscrow
 750 |     |     /// @return The SuperVaultEscrow address at the given index
 751 |     |     function superVaultEscrows(uint256 index) external view returns (address);
 752 |     | 
 753 |     |     /// @notice Validates a hook against both global and strategy-specific Merkle roots
 754 |     |     /// @param strategy Address of the strategy
 755 |     |     /// @param args Arguments for hook validation
 756 |     |     /// @return isValid True if the hook is valid against either root
 757 |     |     function validateHook(
 758 |     |         address strategy,
 759 |     |         ValidateHookArgs calldata args
 760 |     |     )
 761 |     |         external
 762 |     |         view
 763 |     |         returns (bool isValid);
 764 |     | 
 765 |     |     /// @notice Batch validates multiple hooks against Merkle roots
 766 |     |     /// @param strategy Address of the strategy
 767 |     |     /// @param argsArray Array of hook validation arguments
 768 |     |     /// @return validHooks Array of booleans indicating which hooks are valid
 769 |     |     function validateHooks(
 770 |     |         address strategy,
 771 |     |         ValidateHookArgs[] calldata argsArray
 772 |     |     )
 773 |     |         external
 774 |     |         view
 775 |     |         returns (bool[] memory validHooks);
 776 |     | 
 777 |     |     /// @notice Gets the current global hooks Merkle root
 778 |     |     /// @return root The current global hooks Merkle root
 779 |     |     function getGlobalHooksRoot() external view returns (bytes32 root);
 780 |     | 
 781 |     |     /// @notice Gets the proposed global hooks root and effective time
 782 |     |     /// @return root The proposed global hooks Merkle root
 783 |     |     /// @return effectiveTime The timestamp when the proposed root becomes effective
 784 |     |     function getProposedGlobalHooksRoot() external view returns (bytes32 root, uint256 effectiveTime);
 785 |     | 
 786 |     |     /// @notice Checks if the global hooks root is active (timelock period has passed)
 787 |     |     /// @return isActive True if the global hooks root is active
 788 |     |     function isGlobalHooksRootActive() external view returns (bool);
 789 |     | 
 790 |     |     /// @notice Gets the hooks Merkle root for a specific strategy
 791 |     |     /// @param strategy Address of the strategy
 792 |     |     /// @return root The strategy-specific hooks Merkle root
 793 |     |     function getStrategyHooksRoot(address strategy) external view returns (bytes32 root);
 794 |     | 
 795 |     |     /// @notice Gets the proposed strategy hooks root and effective time
 796 |     |     /// @param strategy Address of the strategy
 797 |     |     /// @return root The proposed strategy hooks Merkle root
 798 |     |     /// @return effectiveTime The timestamp when the proposed root becomes effective
 799 |     |     function getProposedStrategyHooksRoot(address strategy)
 800 |     |         external
 801 |     |         view
 802 |     |         returns (bytes32 root, uint256 effectiveTime);
 803 |     | }
 804 |     | 

/opt/scfuzzbench/work/target/src/interfaces/SuperVault/ISuperVaultEscrow.sol
  1 |     | // SPDX-License-Identifier: UNLICENSED
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | /// @title ISuperVaultEscrow
  5 |     | /// @notice Interface for SuperVault escrow contract that holds shares during request/claim process
  6 |     | /// @author Superform Labs
  7 |     | interface ISuperVaultEscrow {
  8 |     |     /*//////////////////////////////////////////////////////////////
  9 |     |                                 ERRORS
 10 |     |     //////////////////////////////////////////////////////////////*/
 11 |     |     error ALREADY_INITIALIZED();
 12 |     |     error UNAUTHORIZED();
 13 |     |     error ZERO_ADDRESS();
 14 |     | 
 15 |     |     /*//////////////////////////////////////////////////////////////
 16 |     |                             INITIALIZATION
 17 |     |     //////////////////////////////////////////////////////////////*/
 18 |     | 
 19 |     |     /// @notice Initialize the escrow with required parameters
 20 |     |     /// @param vaultAddress The vault contract address
 21 |     |     /// @param strategyAddress The strategy contract address
 22 |     |     function initialize(address vaultAddress, address strategyAddress) external;
 23 |     | 
 24 |     |     /*//////////////////////////////////////////////////////////////
 25 |     |                             VAULT FUNCTIONS
 26 |     |     //////////////////////////////////////////////////////////////*/
 27 |     | 
 28 |     |     /// @notice Transfer shares from user to escrow during redeem request
 29 |     |     /// @param from The address to transfer shares from
 30 |     |     /// @param amount The amount of shares to transfer
 31 |     |     function escrowShares(address from, uint256 amount) external;
 32 |     | 
 33 |     |     /// @notice Return shares from escrow to user during redeem cancellation
 34 |     |     /// @param to The address to return shares to
 35 |     |     /// @param amount The amount of shares to return
 36 |     |     function returnShares(address to, uint256 amount) external;
 37 |     | }
 38 |     | 

/opt/scfuzzbench/work/target/src/interfaces/SuperVault/ISuperVaultStrategy.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   5 |     | import { ISuperHook, Execution } from "@superform-v2-core/src/interfaces/ISuperHook.sol";
   6 |     | 
   7 |     | /// @title ISuperVaultStrategy
   8 |     | /// @author Superform Labs
   9 |     | /// @notice Interface for SuperVault strategy implementation that manages yield sources and executes strategies
  10 |     | interface ISuperVaultStrategy {
  11 |     |     /*//////////////////////////////////////////////////////////////
  12 |     |                                 ERRORS
  13 |     |     //////////////////////////////////////////////////////////////*/
  14 |     | 
  15 |     |     error ZERO_LENGTH();
  16 |     |     error INVALID_HOOK();
  17 |     |     error ZERO_ADDRESS();
  18 |     |     error ACCESS_DENIED();
  19 |     |     error INVALID_AMOUNT();
  20 |     |     error INVALID_MANAGER();
  21 |     |     error OPERATION_FAILED();
  22 |     |     error INVALID_TIMESTAMP();
  23 |     |     error REQUEST_NOT_FOUND();
  24 |     |     error INVALID_HOOK_ROOT();
  25 |     |     error INVALID_HOOK_TYPE();
  26 |     |     error INSUFFICIENT_FUNDS();
  27 |     |     error ZERO_OUTPUT_AMOUNT();
  28 |     |     error INSUFFICIENT_SHARES();
  29 |     |     error ZERO_EXPECTED_VALUE();
  30 |     |     error INVALID_ARRAY_LENGTH();
  31 |     |     error ACTION_TYPE_DISALLOWED();
  32 |     |     error YIELD_SOURCE_NOT_FOUND();
  33 |     |     error INVALID_EMERGENCY_ADMIN();
  34 |     |     error INVALID_PERIPHERY_REGISTRY();
  35 |     |     error YIELD_SOURCE_ALREADY_EXISTS();
  36 |     |     error INVALID_PERFORMANCE_FEE_BPS();
  37 |     |     error INVALID_EMERGENCY_WITHDRAWAL();
  38 |     |     error ASYNC_REQUEST_BLOCKING();
  39 |     |     error MINIMUM_PREVIOUS_HOOK_OUT_AMOUNT_NOT_MET();
  40 |     |     error MINIMUM_OUTPUT_AMOUNT_ASSETS_NOT_MET();
  41 |     |     error INVALID_REDEEM_CLAIM();
  42 |     |     error MANAGER_NOT_AUTHORIZED();
  43 |     |     error PPS_UPDATE_RATE_LIMITED();
  44 |     |     error PPS_OUT_OF_BOUNDS();
  45 |     |     error CALCULATION_BLOCK_TOO_OLD();
  46 |     |     error INVALID_PPS();
  47 |     |     error INVALID_REDEEM_FILL();
  48 |     |     error SLIPPAGE_EXCEEDED();
  49 |     |     error INVALID_VAULT();
  50 |     |     error STAKE_TOO_LOW();
  51 |     |     error OPERATIONS_BLOCKED_BY_VETO();
  52 |     |     error HOOK_VALIDATION_FAILED();
  53 |     |     error STRATEGY_PAUSED();
  54 |     |     error INVALID_MAX_SLIPPAGE_BPS();
  55 |     |     error NO_PROPOSAL();
  56 |     | 
  57 |     |     /*//////////////////////////////////////////////////////////////
  58 |     |                                 EVENTS
  59 |     |     //////////////////////////////////////////////////////////////*/
  60 |     | 
  61 |     |     event SuperGovernorSet(address indexed superGovernor);
  62 |     |     event Initialized(address indexed vault);
  63 |     |     event YieldSourceAdded(address indexed source, address indexed oracle);
  64 |     |     event YieldSourceOracleUpdated(address indexed source, address indexed oldOracle, address indexed newOracle);
  65 |     |     event YieldSourceRemoved(address indexed source);
  66 |     | 
  67 |     |     event HookRootUpdated(bytes32 newRoot);
  68 |     |     event HookRootProposed(bytes32 proposedRoot, uint256 effectiveTime);
  69 |     |     event EmergencyWithdrawableProposed(bool newWithdrawable, uint256 effectiveTime);
  70 |     |     event EmergencyWithdrawableUpdated(bool withdrawable);
  71 |     |     event EmergencyWithdrawableProposalCanceled();
  72 |     |     event EmergencyWithdrawal(address indexed recipient, uint256 assets);
  73 |     |     event VaultFeeConfigUpdated(uint256 performanceFeeBps, uint256 managementFeeBps, address indexed recipient);
  74 |     |     event VaultFeeConfigProposed(
  75 |     |         uint256 performanceFeeBps, uint256 managementFeeBps, address indexed recipient, uint256 effectiveTime
  76 |     |     );
  77 |     |     event MaxPPSSlippageUpdated(uint256 maxSlippageBps);
  78 |     |     event HooksExecuted(address[] hooks);
  79 |     |     event RedeemRequestPlaced(address indexed controller, address indexed owner, uint256 shares);
  80 |     |     event RedeemRequestFulfilled(address indexed controller, address indexed receiver, uint256 assets, uint256 shares);
  81 |     |     event RedeemRequestCanceled(address indexed controller, uint256 shares);
  82 |     |     event HookExecuted(
  83 |     |         address indexed hook,
  84 |     |         address indexed prevHook,
  85 |     |         address indexed targetedYieldSource,
  86 |     |         bool usePrevHookAmount,
  87 |     |         bytes hookCalldata
  88 |     |     );
  89 |     |     event FulfillHookExecuted(address indexed hook, address indexed targetedYieldSource, bytes hookCalldata);
  90 |     | 
  91 |     |     event PPSUpdated(uint256 newPPS, uint256 calculationBlock);
  92 |     | 
  93 |     |     event RedeemRequestsFulfilled(address[] hooks, address[] controllers, uint256 processedShares, uint256 currentPPS);
  94 |     | 
  95 |     |     event FeePaid(address indexed recipient, uint256 amount, uint256 performanceFeeBps);
  96 |     |     event ManagementFeePaid(address indexed controller, address indexed recipient, uint256 feeAssets, uint256 feeBps);
  97 |     |     event DepositHandled(address indexed controller, uint256 assets, uint256 shares);
  98 |     | 
  99 |     |     /*//////////////////////////////////////////////////////////////
 100 |     |                                 STRUCTS
 101 |     |     //////////////////////////////////////////////////////////////*/
 102 |     | 
 103 |     |     struct FeeConfig {
 104 |     |         uint256 performanceFeeBps; // On profit at fulfill time
 105 |     |         uint256 managementFeeBps; // Entry fee on deposit/mint (asset-side)
 106 |     |         address recipient; // Fee sink (entry + performance)
 107 |     |     }
 108 |     | 
 109 |     |     /// @notice Structure for hook execution arguments
 110 |     |     struct ExecuteArgs {
 111 |     |         /// @notice Array of hooks to execute
 112 |     |         address[] hooks;
 113 |     |         /// @notice Calldata for each hook (must match hooks array length)
 114 |     |         bytes[] hookCalldata;
 115 |     |         /// @notice Expected output amounts or output shares
 116 |     |         uint256[] expectedAssetsOrSharesOut;
 117 |     |         /// @notice Global Merkle proofs for hook validation (must match hooks array length)
 118 |     |         bytes32[][] globalProofs;
 119 |     |         /// @notice Strategy-specific Merkle proofs for hook validation (must match hooks array length)
 120 |     |         bytes32[][] strategyProofs;
 121 |     |     }
 122 |     | 
 123 |     |     struct FulfillArgs {
 124 |     |         address[] controllers;
 125 |     |         address[] hooks;
 126 |     |         bytes[] hookCalldata;
 127 |     |         uint256[] expectedAssetsOrSharesOut;
 128 |     |         bytes32[][] globalProofs;
 129 |     |         bytes32[][] strategyProofs;
 130 |     |     }
 131 |     | 
 132 |     |     struct YieldSource {
 133 |     |         address oracle; // Associated yield source oracle address
 134 |     |     }
 135 |     | 
 136 |     |     /// @notice Comprehensive information about a yield source including its address and configuration
 137 |     |     struct YieldSourceInfo {
 138 |     |         address sourceAddress; // Address of the yield source
 139 |     |         address oracle; // Associated yield source oracle address
 140 |     |     }
 141 |     | 
 142 |     |     /// @notice State specific to asynchronous redeem requests
 143 |     |     struct SuperVaultState {
 144 |     |         uint256 pendingRedeemRequest; // Shares requested
 145 |     |         uint256 maxWithdraw; // Assets claimable after fulfillment
 146 |     |         uint256 averageRequestPPS; // Average PPS at the time of redeem request
 147 |     |         // Accumulators needed for fee calculation on redeem
 148 |     |         uint256 accumulatorShares;
 149 |     |         uint256 accumulatorCostBasis;
 150 |     |         uint256 averageWithdrawPrice; // Average price for claimable assets
 151 |     |     }
 152 |     | 
 153 |     |     struct ExecutionVars {
 154 |     |         bool success;
 155 |     |         address targetedYieldSource;
 156 |     |         uint256 outAmount;
 157 |     |         ISuperHook hookContract;
 158 |     |         Execution[] executions;
 159 |     |     }
 160 |     | 
 161 |     |     struct OutflowExecutionVars {
 162 |     |         bool success;
 163 |     |         address targetedYieldSource;
 164 |     |         address svAsset;
 165 |     |         uint256 outAmount;
 166 |     |         uint256 superVaultShares;
 167 |     |         uint256 amountOfAssets;
 168 |     |         uint256 amountConvertedToUnderlyingShares;
 169 |     |         uint256 balanceAssetBefore;
 170 |     |         Execution[] executions;
 171 |     |         ISuperHook hookContract;
 172 |     |         ISuperHook.HookType hookType;
 173 |     |     }
 174 |     | 
 175 |     |     /*//////////////////////////////////////////////////////////////
 176 |     |                                 ENUMS
 177 |     |     //////////////////////////////////////////////////////////////*/
 178 |     |     enum Operation {
 179 |     |         Deposit,
 180 |     |         RedeemRequest,
 181 |     |         CancelRedeem,
 182 |     |         ClaimRedeem,
 183 |     |         Claim,
 184 |     |         UpdateDepositAccumulators
 185 |     |     }
 186 |     | 
 187 |     |     /*//////////////////////////////////////////////////////////////
 188 |     |                         CORE STRATEGY OPERATIONS
 189 |     |     //////////////////////////////////////////////////////////////*/
 190 |     | 
 191 |     |     /// @notice Initializes the strategy with required parameters
 192 |     |     /// @param vaultAddress Address of the associated SuperVault
 193 |     |     /// @param feeConfigData Fee configuration
 194 |     |     function initialize(address vaultAddress, FeeConfig memory feeConfigData) external;
 195 |     | 
 196 |     |     /// @notice Execute a 4626 deposit by processing assets.
 197 |     |     /// @param controller The controller address
 198 |     |     /// @param assetsGross The amount of gross assets user has to deposit
 199 |     |     /// @return sharesNet The amount of net shares to mint
 200 |     |     function handleOperations4626Deposit(
 201 |     |         address controller,
 202 |     |         uint256 assetsGross
 203 |     |     )
 204 |     |         external
 205 |     |         returns (uint256 sharesNet);
 206 |     | 
 207 |     |     /// @notice Execute a 4626 mint by processing shares.
 208 |     |     /// @param controller The controller address
 209 |     |     /// @param sharesNet The amount of shares to mint
 210 |     |     /// @param assetsGross The amount of gross assets user has to deposit
 211 |     |     /// @param assetsNet The amount of net assets that strategy will receive
 212 |     |     function handleOperations4626Mint(
 213 |     |         address controller,
 214 |     |         uint256 sharesNet,
 215 |     |         uint256 assetsGross,
 216 |     |         uint256 assetsNet
 217 |     |     )
 218 |     |         external;
 219 |     | 
 220 |     |     /// @notice Quotes the amount of assets that will be received for a given amount of shares.
 221 |     |     /// @param shares The amount of shares to mint
 222 |     |     /// @return assetsGross The amount of gross assets that will be received
 223 |     |     /// @return assetsNet The amount of net assets that will be received
 224 |     |     function quoteMintAssetsGross(uint256 shares) external view returns (uint256 assetsGross, uint256 assetsNet);
 225 |     | 
 226 |     |     /// @notice Execute async redeem requests (redeem, cancel, claim).
 227 |     |     /// @param op The operation type (RedeemRequest, CancelRedeem, ClaimRedeem)
 228 |     |     /// @param controller The controller address
 229 |     |     /// @param receiver The receiver address
 230 |     |     /// @param amount The amount of assets or shares
 231 |     |     function handleOperations7540(Operation op, address controller, address receiver, uint256 amount) external;
 232 |     | 
 233 |     |     /*//////////////////////////////////////////////////////////////
 234 |     |                 MANAGER EXTERNAL ACCESS FUNCTIONS
 235 |     |     //////////////////////////////////////////////////////////////*/
 236 |     | 
 237 |     |     /// @notice Execute hooks for general strategy management (rebalancing, etc.).
 238 |     |     /// @param args Execution arguments containing hooks, calldata, proofs, expectations.
 239 |     |     function executeHooks(ExecuteArgs calldata args) external payable;
 240 |     | 
 241 |     |     /// @notice Fulfills pending redeem requests by executing specific fulfill hooks.
 242 |     |     /// @param args Execution arguments containing fulfill hooks, calldata, and expected outputs (proofs ignored).
 243 |     |     function fulfillRedeemRequests(FulfillArgs calldata args) external;
 244 |     | 
 245 |     |     /*//////////////////////////////////////////////////////////////
 246 |     |                         YIELD SOURCE MANAGEMENT
 247 |     |     //////////////////////////////////////////////////////////////*/
 248 |     | 
 249 |     |     /// @notice Manage a single yield source: add, update oracle, or remove
 250 |     |     /// @param source Address of the yield source
 251 |     |     /// @param oracle Address of the oracle (used for adding/updating, ignored for removal)
 252 |     |     /// @param actionType Type of action: 0=Add, 1=UpdateOracle, 2=Remove
 253 |     |     function manageYieldSource(address source, address oracle, uint8 actionType) external;
 254 |     | 
 255 |     |     /// @notice Batch manage multiple yield sources in a single transaction
 256 |     |     /// @param sources Array of yield source addresses
 257 |     |     /// @param oracles Array of oracle addresses (used for adding/updating, ignored for removal)
 258 |     |     /// @param actionTypes Array of action types: 0=Add, 1=UpdateOracle, 2=Remove
 259 |     |     function manageYieldSources(
 260 |     |         address[] calldata sources,
 261 |     |         address[] calldata oracles,
 262 |     |         uint8[] calldata actionTypes
 263 |     |     )
 264 |     |         external;
 265 |     | 
 266 |     |     /// @notice Propose or execute a hook root update
 267 |     |     /// @notice Propose changes to vault-specific fee configuration
 268 |     |     /// @param performanceFeeBps New performance fee in basis points
 269 |     |     /// @param managementFeeBps New management fee in basis points
 270 |     |     /// @param recipient New fee recipient
 271 |     |     function proposeVaultFeeConfigUpdate(
 272 |     |         uint256 performanceFeeBps,
 273 |     |         uint256 managementFeeBps,
 274 |     |         address recipient
 275 |     |     )
 276 |     |         external;
 277 |     | 
 278 |     |     /// @notice Execute the proposed vault fee configuration update after timelock
 279 |     |     function executeVaultFeeConfigUpdate() external;
 280 |     | 
 281 |     |     /// @notice Update the maximum allowed PPS slippage for redemptions
 282 |     |     /// @param maxSlippageBps Maximum slippage in basis points (e.g., 100 = 1%)
 283 |     |     function updateMaxPPSSlippage(uint256 maxSlippageBps) external;
 284 |     | 
 285 |     |     /// @notice Manage emergency withdrawals
 286 |     |     /// @param action Type of action: 1=Propose, 2=ExecuteActivation, 3=Withdraw, 4=CancelProposal
 287 |     |     /// @param recipient The recipient of the withdrawn assets (for action 3)
 288 |     |     /// @param amount The amount of assets to withdraw (for action 3)
 289 |     |     function manageEmergencyWithdraw(uint8 action, address recipient, uint256 amount) external;
 290 |     | 
 291 |     |     /*//////////////////////////////////////////////////////////////
 292 |     |                         ACCOUNTING MANAGEMENT
 293 |     |     //////////////////////////////////////////////////////////////*/
 294 |     |     /// @notice Move accumulator shares and cost basis pro-rata during share transfers
 295 |     |     /// @param from The address transferring shares
 296 |     |     /// @param to The address receiving shares
 297 |     |     /// @param shares The amount of shares being transferred
 298 |     |     function moveAccumulatorOnTransfer(address from, address to, uint256 shares) external;
 299 |     | 
 300 |     |     /*//////////////////////////////////////////////////////////////
 301 |     |                             VIEW FUNCTIONS
 302 |     |     //////////////////////////////////////////////////////////////*/
 303 |     | 
 304 |     |     /// @notice Get the vault info
 305 |     |     function getVaultInfo() external view returns (address vault, address asset, uint8 vaultDecimals);
 306 |     | 
 307 |     |     /// @notice Get the fee configurations
 308 |     |     function getConfigInfo() external view returns (FeeConfig memory feeConfig);
 309 |     | 
 310 |     |     /// @notice Returns the currently stored PPS value.
 311 |     |     function getStoredPPS() external view returns (uint256);
 312 |     | 
 313 |     |     /// @notice Get a yield source's configuration
 314 |     |     function getYieldSource(address source) external view returns (YieldSource memory);
 315 |     | 
 316 |     |     /// @notice Get all yield sources with their information
 317 |     |     /// @return Array of YieldSourceInfo structs
 318 |     |     function getYieldSourcesList() external view returns (YieldSourceInfo[] memory);
 319 |     | 
 320 |     |     /// @notice Get all yield source addresses
 321 |     |     /// @return Array of yield source addresses
 322 |     |     function getYieldSources() external view returns (address[] memory);
 323 |     | 
 324 |     |     /// @notice Get the count of yield sources
 325 |     |     /// @return Number of yield sources
 326 |     |     function getYieldSourcesCount() external view returns (uint256);
 327 |     | 
 328 |     |     /// @notice Check if a yield source exists
 329 |     |     /// @param source Address of the yield source
 330 |     |     /// @return True if the yield source exists
 331 |     |     function containsYieldSource(address source) external view returns (bool);
 332 |     | 
 333 |     |     /// @notice Get the average withdraw price for a controller
 334 |     |     /// @param controller The controller address
 335 |     |     /// @return averageWithdrawPrice The average withdraw price
 336 |     |     function getAverageWithdrawPrice(address controller) external view returns (uint256 averageWithdrawPrice);
 337 |     | 
 338 |     |     /// @notice Get the super vault state for a controller
 339 |     |     /// @param controller The controller address
 340 |     |     /// @return state The super vault state
 341 |     |     function getSuperVaultState(address controller) external view returns (SuperVaultState memory state);
 342 |     | 
 343 |     |     /// @notice Previews the fee that would be taken for redeeming a specific amount of shares
 344 |     |     /// @param controller The address of the controller requesting the redemption
 345 |     |     /// @param sharesToRedeem The number of shares to redeem
 346 |     |     /// @return totalFee The estimated fee that would be taken in asset terms
 347 |     |     /// @return superformFee The portion of the fee that would go to Superform treasury
 348 |     |     /// @return recipientFee The portion of the fee that would go to the fee recipient
 349 |     |     function previewPerformanceFee(
 350 |     |         address controller,
 351 |     |         uint256 sharesToRedeem
 352 |     |     )
 353 |     |         external
 354 |     |         view
 355 |     |         returns (uint256 totalFee, uint256 superformFee, uint256 recipientFee);
 356 |     | 
 357 |     |     /// @notice Get the pending redeem request amount (shares) for a controller
 358 |     |     /// @param controller The controller address
 359 |     |     /// @return pendingShares The amount of shares pending redemption
 360 |     |     function pendingRedeemRequest(address controller) external view returns (uint256 pendingShares);
 361 |     | 
 362 |     |     /// @notice Get the claimable withdraw amount (assets) for a controller
 363 |     |     /// @param controller The controller address
 364 |     |     /// @return claimableAssets The amount of assets claimable
 365 |     |     function claimableWithdraw(address controller) external view returns (uint256 claimableAssets);
 366 |     | }
 367 |     | 

/opt/scfuzzbench/work/target/src/interfaces/oracles/IECDSAPPSOracle.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | /// @title ECDSAPPSOracle
   5 |     | /// @author Superform Labs
   6 |     | /// @notice Interface for PPS oracles that provide price-per-share updates
   7 |     | /// @dev All PPS oracle implementations must conform to this interface
   8 |     | interface IECDSAPPSOracle {
   9 |     |     /*//////////////////////////////////////////////////////////////
  10 |     |                                  ERRORS
  11 |     |     //////////////////////////////////////////////////////////////*/
  12 |     |     /// @notice Thrown when the proof is invalid or cannot be verified
  13 |     |     error INVALID_PROOF();
  14 |     |     /// @notice Thrown when a validator is not registered or authorized
  15 |     |     error INVALID_VALIDATOR();
  16 |     |     /// @notice Thrown when the quorum of validators is not met
  17 |     |     error QUORUM_NOT_MET();
  18 |     |     /// @notice Thrown when the input arrays have different lengths
  19 |     |     error ARRAY_LENGTH_MISMATCH();
  20 |     |     /// @notice Thrown when the input array is empty
  21 |     |     error ZERO_LENGTH_ARRAY();
  22 |     |     /// @notice Thrown when the timestamp in the proof is invalid
  23 |     |     error INVALID_TIMESTAMP();
  24 |     |     /// @notice Thrown when the strategy address in the proof does not match
  25 |     |     error STRATEGY_MISMATCH();
  26 |     |     /// @notice Thrown when the pps value in the proof does not match
  27 |     |     error PPS_MISMATCH();
  28 |     |     /// @notice Thrown when the oracle is not set as the active PPS Oracle in SuperGovernor
  29 |     |     error NOT_ACTIVE_PPS_ORACLE();
  30 |     |     /// @notice Thrown when the dispersion (standard deviation / mean) is too high
  31 |     |     error HIGH_PPS_DISPERSION();
  32 |     |     /// @notice Thrown when the deviation from previous PPS is too high
  33 |     |     error HIGH_PPS_DEVIATION();
  34 |     |     /// @notice Thrown when too few validators participated in the round
  35 |     |     error INSUFFICIENT_VALIDATOR_PARTICIPATION();
  36 |     |     /// @notice Thrown when the reported validator count doesn't match the actual number of valid signatures
  37 |     |     error VALIDATOR_COUNT_MISMATCH();
  38 |     |     /// @notice Thrown when the validatorSet doesn't match the actual number of valid signatures  
  39 |     |     error INVALID_VALIDATOR_SET();
  40 |     |     /// @notice Thrown when the totalValidators doesn't match the actual total number of validators
  41 |     |     error INVALID_TOTAL_VALIDATORS();
  42 |     | 
  43 |     |     /*//////////////////////////////////////////////////////////////
  44 |     |                                  EVENTS
  45 |     |     //////////////////////////////////////////////////////////////*/
  46 |     |     /// @notice Emitted when a PPS update is validated and forwarded
  47 |     |     /// @param strategy Address of the strategy
  48 |     |     /// @param pps The validated price-per-share value
  49 |     |     /// @param ppsStdev The standard deviation of the price-per-share
  50 |     |     /// @param validatorSet Number of validators who calculated the PPS
  51 |     |     /// @param totalValidators Total number of validators in the network
  52 |     |     /// @param timestamp Timestamp when the value was generated
  53 |     |     /// @param sender Address that submitted the update
  54 |     |     event PPSValidated(
  55 |     |         address indexed strategy,
  56 |     |         uint256 pps,
  57 |     |         uint256 ppsStdev,
  58 |     |         uint256 validatorSet,
  59 |     |         uint256 totalValidators,
  60 |     |         uint256 timestamp,
  61 |     |         address indexed sender
  62 |     |     );
  63 |     | 
  64 |     |     /// @notice Emitted when proof validation failed
  65 |     |     /// @param strategy Address of the strategy
  66 |     |     /// @param reason Revert reason
  67 |     |     event ProofValidationFailed(address indexed strategy, string reason);
  68 |     | 
  69 |     |     /// @notice Emitted when proof validation failed
  70 |     |     /// @param strategy Address of the strategy
  71 |     |     /// @param data Revert encoded data
  72 |     |     event ProofValidationFailedLowLevel(address indexed strategy, bytes data);
  73 |     | 
  74 |     |     /// @notice Emitted when batch forward PPS failed
  75 |     |     /// @param reason Revert reason
  76 |     |     event BatchForwardPPSFailed(string reason);
  77 |     | 
  78 |     |     /// @notice Emitted when batch forward PPS failed
  79 |     |     /// @param lowLevelData Revert encoded data
  80 |     |     event BatchForwardPPSFailedLowLevel(bytes lowLevelData);
  81 |     | 
  82 |     |     /*//////////////////////////////////////////////////////////////
  83 |     |                             STRUCTS
  84 |     |     //////////////////////////////////////////////////////////////*/
  85 |     |     /// @notice Parameters for validating PPS proofs
  86 |     |     /// @param strategy Address of the strategy
  87 |     |     /// @param proofs Array of cryptographic proofs
  88 |     |     /// @param pps Price-per-share value (mean)
  89 |     |     /// @param ppsStdev Standard deviation of the price-per-share
  90 |     |     /// @param validatorSet Number of validators who calculated this PPS
  91 |     |     /// @param totalValidators Total number of validators in the network
  92 |     |     /// @param timestamp Timestamp when the value was generated
  93 |     |     struct ValidationParams {
  94 |     |         address strategy;
  95 |     |         bytes[] proofs;
  96 |     |         uint256 pps;
  97 |     |         uint256 ppsStdev;
  98 |     |         uint256 validatorSet;
  99 |     |         uint256 totalValidators;
 100 |     |         uint256 timestamp;
 101 |     |     }
 102 |     | 
 103 |     |     /// @notice Arguments for batch updating PPS for multiple strategies
 104 |     |     /// @param strategies Array of strategy addresses
 105 |     |     /// @param proofsArray Array of arrays of cryptographic proofs (one array of proofs per strategy)
 106 |     |     /// @param ppss Array of price-per-share values (means)
 107 |     |     /// @param ppsStdevs Array of standard deviations of price-per-share values
 108 |     |     /// @param validatorSets Array of numbers of validators who calculated each PPS
 109 |     |     /// @param totalValidators Array of total number of validators in the network for each update
 110 |     |     /// @param timestamps The time and therefore the blockchain(s) state(s) (plural important) this PPS refers to
 111 |     |     struct UpdatePPSArgs {
 112 |     |         address[] strategies;
 113 |     |         bytes[][] proofsArray;
 114 |     |         uint256[] ppss;
 115 |     |         uint256[] ppsStdevs;
 116 |     |         uint256[] validatorSets;
 117 |     |         uint256[] totalValidators;
 118 |     |         uint256[] timestamps;
 119 |     |     }
 120 |     | 
 121 |     |     /*//////////////////////////////////////////////////////////////
 122 |     |                               VIEW FUNCTIONS
 123 |     |     //////////////////////////////////////////////////////////////*/
 124 |     |     /// @notice Returns the current nonce
 125 |     |     /// @param strategy_ Address of the strategy
 126 |     |     /// @return The current nonce
 127 |     |     function noncePerStrategy(address strategy_) external view returns (uint256);
 128 |     | 
 129 |     |     /// @notice Returns the domain separator for the contract
 130 |     |     /// @return The domain separator
 131 |     |     function domainSeparator() external view returns (bytes32);
 132 |     | 
 133 |     |     /// @notice Returns the signature typehash
 134 |     |     /// @return The typehash
 135 |     |     function UPDATE_PPS_TYPEHASH() external view returns (bytes32);
 136 |     | 
 137 |     |     /// @notice Validates an array of proofs for a strategy's PPS update
 138 |     |     /// @param params Validation parameters
 139 |     |     /// @dev Reverts immediately if duplicate signers are found or quorum is not met
 140 |     |     function validateProofs(IECDSAPPSOracle.ValidationParams memory params) external view;
 141 |     | 
 142 |     |     /*//////////////////////////////////////////////////////////////
 143 |     |                             EXTERNAL FUNCTIONS
 144 |     |     //////////////////////////////////////////////////////////////*/
 145 |     |     /// @notice Updates the PPS for multiple strategies in a batch
 146 |     |     /// @param args Struct containing all parameters for batch PPS update
 147 |     |     function updatePPS(UpdatePPSArgs calldata args) external;
 148 |     | }
 149 |     | 

/opt/scfuzzbench/work/target/src/interfaces/oracles/ISuperOracle.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity 0.8.30;
   3 |     | 
   4 |     | /// @title ISuperOracle
   5 |     | /// @author Superform Labs
   6 |     | /// @notice Interface for SuperOracle
   7 |     | interface ISuperOracle {
   8 |     |     /*//////////////////////////////////////////////////////////////
   9 |     |                                 ERRORS
  10 |     |     //////////////////////////////////////////////////////////////*/
  11 |     |     /// @notice Error when address is zero
  12 |     |     error ZERO_ADDRESS();
  13 |     | 
  14 |     |     /// @notice Error when array length is zero
  15 |     |     error ZERO_ARRAY_LENGTH();
  16 |     | 
  17 |     |     /// @notice Error when oracle provider index is invalid
  18 |     |     error INVALID_ORACLE_PROVIDER();
  19 |     | 
  20 |     |     /// @notice Error when no oracles are configured for base asset
  21 |     |     error NO_ORACLES_CONFIGURED();
  22 |     | 
  23 |     |     /// @notice Error when no valid reported prices are found
  24 |     |     error NO_VALID_REPORTED_PRICES();
  25 |     | 
  26 |     |     /// @notice Error when caller is not admin
  27 |     |     error NOT_ADMIN();
  28 |     | 
  29 |     |     /// @notice Error when arrays have mismatched lengths
  30 |     |     error ARRAY_LENGTH_MISMATCH();
  31 |     | 
  32 |     |     /// @notice Error when timelock period has not elapsed
  33 |     |     error TIMELOCK_NOT_ELAPSED();
  34 |     | 
  35 |     |     /// @notice Error when there is already a pending update
  36 |     |     error PENDING_UPDATE_EXISTS();
  37 |     | 
  38 |     |     /// @notice Error when oracle data is untrusted
  39 |     |     error ORACLE_UNTRUSTED_DATA();
  40 |     | 
  41 |     |     /// @notice Error when provider max staleness period is not set
  42 |     |     error NO_PENDING_UPDATE();
  43 |     | 
  44 |     |     /// @notice Error when quote is not supported (only USD is supported)
  45 |     |     error UNSUPPORTED_QUOTE();
  46 |     | 
  47 |     |     /// @notice Error when provider max staleness period is exceeded
  48 |     |     error MAX_STALENESS_EXCEEDED();
  49 |     | 
  50 |     |     /// @notice Error when no prices are reported
  51 |     |     error NO_PRICES();
  52 |     | 
  53 |     |     /// @notice Error when average provider is not allowed
  54 |     |     error AVERAGE_PROVIDER_NOT_ALLOWED();
  55 |     | 
  56 |     |     /// @notice Error when provider is zero
  57 |     |     error ZERO_PROVIDER();
  58 |     | 
  59 |     |     /// @notice Error when caller is not authorized to update
  60 |     |     error UNAUTHORIZED_UPDATE_AUTHORITY();
  61 |     | 
  62 |     |     /// @notice Error when oracle decimals call fails
  63 |     |     error ORACLE_DECIMALS_CALL_FAIL(address oracle);
  64 |     | 
  65 |     |     /// @notice Error when oracle round data call fails 
  66 |     |     error ORACLE_ROUND_DATA_CALL_FAIL(address oracle);
  67 |     | 
  68 |     |     /*//////////////////////////////////////////////////////////////
  69 |     |                                 EVENTS
  70 |     |     //////////////////////////////////////////////////////////////*/
  71 |     |     /// @notice Emitted when oracles are configured
  72 |     |     /// @param bases Array of base assets
  73 |     |     /// @param providers Array of provider indexes
  74 |     |     /// @param feeds Array of oracle addresses
  75 |     |     event OraclesConfigured(address[] bases, address[] quotes, bytes32[] providers, address[] feeds);
  76 |     | 
  77 |     |     /// @notice Emitted when oracle update is queued
  78 |     |     /// @param bases Array of base assets
  79 |     |     /// @param providers Array of provider indexes
  80 |     |     /// @param feeds Array of oracle addresses
  81 |     |     /// @param timestamp Timestamp when update was queued
  82 |     |     event OracleUpdateQueued(
  83 |     |         address[] bases, address[] quotes, bytes32[] providers, address[] feeds, uint256 timestamp
  84 |     |     );
  85 |     | 
  86 |     |     /// @notice Emitted when oracle update is executed
  87 |     |     /// @param bases Array of base assets
  88 |     |     /// @param providers Array of provider indexes
  89 |     |     /// @param feeds Array of oracle addresses
  90 |     |     event OracleUpdateExecuted(address[] bases, address[] quotes, bytes32[] providers, address[] feeds);
  91 |     | 
  92 |     |     /// @notice Emitted when provider max staleness period is updated
  93 |     |     /// @param feed Feed address
  94 |     |     /// @param newMaxStaleness New maximum staleness period in seconds
  95 |     |     event FeedMaxStalenessUpdated(address feed, uint256 newMaxStaleness);
  96 |     | 
  97 |     |     /// @notice Emitted when max staleness period is updated
  98 |     |     /// @param newMaxStaleness New maximum staleness period in seconds
  99 |     |     event MaxStalenessUpdated(uint256 newMaxStaleness);
 100 |     | 
 101 |     |     /// @notice Emitted when provider removal is queued
 102 |     |     /// @param providers Array of provider ids to remove
 103 |     |     /// @param timestamp Timestamp when removal was queued
 104 |     |     event ProviderRemovalQueued(bytes32[] providers, uint256 timestamp);
 105 |     | 
 106 |     |     /// @notice Emitted when provider removal is executed
 107 |     |     /// @param providers Array of provider ids that were removed
 108 |     |     event ProviderRemovalExecuted(bytes32[] providers);
 109 |     | 
 110 |     |     /// @notice Emitted when emergency price is updated
 111 |     |     /// @param token Token address
 112 |     |     /// @param price Emergency price
 113 |     |     event EmergencyPriceUpdated(address token, uint256 price);
 114 |     | 
 115 |     |     /*//////////////////////////////////////////////////////////////
 116 |     |                                 STRUCTS
 117 |     |     //////////////////////////////////////////////////////////////*/
 118 |     |     /// @notice Struct for pending oracle update
 119 |     |     struct PendingUpdate {
 120 |     |         address[] bases;
 121 |     |         address[] quotes;
 122 |     |         bytes32[] providers;
 123 |     |         address[] feeds;
 124 |     |         uint256 timestamp;
 125 |     |     }
 126 |     | 
 127 |     |     /// @notice Struct for pending provider removal
 128 |     |     struct PendingRemoval {
 129 |     |         bytes32[] providers;
 130 |     |         uint256 timestamp;
 131 |     |     }
 132 |     | 
 133 |     |     /*//////////////////////////////////////////////////////////////
 134 |     |                             EXTERNAL FUNCTIONS
 135 |     |     //////////////////////////////////////////////////////////////*/
 136 |     | 
 137 |     |     /// @notice Get oracle address for a base asset and provider
 138 |     |     /// @param base Base asset address
 139 |     |     /// @param quote Quote asset address
 140 |     |     /// @param provider Provider id
 141 |     |     /// @return oracle Oracle address
 142 |     |     function getOracleAddress(address base, address quote, bytes32 provider) external view returns (address oracle);
 143 |     | 
 144 |     |     /// @notice Get quote from specified oracle provider
 145 |     |     /// @param baseAmount Amount of base asset
 146 |     |     /// @param base Base asset address
 147 |     |     /// @param quote Quote asset address
 148 |     |     /// @param oracleProvider Id of oracle provider to use
 149 |     |     /// @return quoteAmount The quote amount
 150 |     |     function getQuoteFromProvider(
 151 |     |         uint256 baseAmount,
 152 |     |         address base,
 153 |     |         address quote,
 154 |     |         bytes32 oracleProvider
 155 |     |     )
 156 |     |         external
 157 |     |         view
 158 |     |         returns (uint256 quoteAmount, uint256 deviation, uint256 totalProviders, uint256 availableProviders);
 159 |     | 
 160 |     |     /// @notice Queue oracle update for timelock
 161 |     |     /// @param bases Array of base assets
 162 |     |     /// @param providers Array of provider ids
 163 |     |     /// @param quotes Array of quote assets
 164 |     |     /// @param feeds Array of oracle addresses
 165 |     |     function queueOracleUpdate(
 166 |     |         address[] calldata bases,
 167 |     |         address[] calldata quotes,
 168 |     |         bytes32[] calldata providers,
 169 |     |         address[] calldata feeds
 170 |     |     )
 171 |     |         external;
 172 |     | 
 173 |     |     /// @notice Execute queued oracle update after timelock period
 174 |     |     function executeOracleUpdate() external;
 175 |     | 
 176 |     |     /// @notice Queue provider removal for timelock
 177 |     |     /// @param providers Array of provider ids to remove
 178 |     |     function queueProviderRemoval(bytes32[] calldata providers) external;
 179 |     | 
 180 |     |     /// @notice Execute queued provider removal after timelock period
 181 |     |     function executeProviderRemoval() external;
 182 |     | 
 183 |     |     /// @notice Set the maximum staleness period for a specific provider
 184 |     |     /// @param feed Feed address
 185 |     |     /// @param newMaxStaleness New maximum staleness period in seconds
 186 |     |     function setFeedMaxStaleness(address feed, uint256 newMaxStaleness) external;
 187 |     | 
 188 |     |     /// @notice Set the maximum staleness period for all providers
 189 |     |     /// @param newMaxStaleness New maximum staleness period in seconds
 190 |     |     function setMaxStaleness(uint256 newMaxStaleness) external;
 191 |     | 
 192 |     |     /// @notice Set the maximum staleness period for multiple providers
 193 |     |     /// @param feeds Array of feed addresses
 194 |     |     /// @param newMaxStalenessList Array of new maximum staleness periods in seconds
 195 |     |     function setFeedMaxStalenessBatch(address[] calldata feeds, uint256[] calldata newMaxStalenessList) external;
 196 |     | 
 197 |     |     /// @notice Get all active provider ids
 198 |     |     /// @return Array of active provider ids
 199 |     |     function getActiveProviders() external view returns (bytes32[] memory);
 200 |     | 
 201 |     |     /// @notice Get the emergency price for a token
 202 |     |     /// @param token Token address
 203 |     |     /// @return Emergency price
 204 |     |     function getEmergencyPrice(address token) external view returns (uint256);
 205 |     | 
 206 |     |     /// @notice Set the emergency price for a token
 207 |     |     /// @param token Token address
 208 |     |     /// @param price Emergency price
 209 |     |     function setEmergencyPrice(address token, uint256 price) external;
 210 |     | 
 211 |     |     /// @notice Set the emergency price for multiple tokens in a batch
 212 |     |     /// @param tokens Array of token addresses
 213 |     |     /// @param prices Array of emergency prices
 214 |     |     function batchSetEmergencyPrice(address[] calldata tokens, uint256[] calldata prices) external;
 215 |     | }
 216 |     | 

/opt/scfuzzbench/work/target/src/interfaces/oracles/ISuperOracleL2.sol
  1 |     | // SPDX-License-Identifier: UNLICENSED
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | /// @title ISuperOracleL2
  5 |     | /// @author Superform Labs
  6 |     | /// @notice Interface for Layer 2 Oracle for Superform
  7 |     | interface ISuperOracleL2 {
  8 |     |     /*//////////////////////////////////////////////////////////////
  9 |     |                             ERRORS
 10 |     |     //////////////////////////////////////////////////////////////*/
 11 |     |     /// @notice Error when no uptime feed is configured for the data oracle
 12 |     |     error NO_UPTIME_FEED();
 13 |     | 
 14 |     |     /// @notice Error when the L2 sequencer is down
 15 |     |     error SEQUENCER_DOWN();
 16 |     | 
 17 |     |     /// @notice Error when the grace period after sequencer restart is not over
 18 |     |     error GRACE_PERIOD_NOT_OVER();
 19 |     | 
 20 |     |     /*//////////////////////////////////////////////////////////////
 21 |     |                             EVENTS
 22 |     |     //////////////////////////////////////////////////////////////*/
 23 |     |     /// @notice Emitted when an uptime feed is set for a data oracle
 24 |     |     /// @param dataOracle The data oracle address
 25 |     |     /// @param uptimeOracle The uptime feed address
 26 |     |     event UptimeFeedSet(address dataOracle, address uptimeOracle);
 27 |     | 
 28 |     |     /// @notice Emitted when a grace period is set for an uptime oracle
 29 |     |     /// @param uptimeOracle The uptime oracle address
 30 |     |     /// @param gracePeriod The grace period in seconds
 31 |     |     event GracePeriodSet(address uptimeOracle, uint256 gracePeriod);
 32 |     | 
 33 |     |     /*//////////////////////////////////////////////////////////////
 34 |     |                             EXTERNAL FUNCTIONS
 35 |     |     //////////////////////////////////////////////////////////////*/
 36 |     |     /// @notice Set uptime feeds for multiple data oracles in batch
 37 |     |     /// @param dataOracles Array of data oracle addresses to set uptime feeds for
 38 |     |     /// @param uptimeOracles Array of uptime feed addresses to set
 39 |     |     /// @param gracePeriods Array of grace periods in seconds after sequencer restart
 40 |     |     function batchSetUptimeFeed(
 41 |     |         address[] calldata dataOracles,
 42 |     |         address[] calldata uptimeOracles,
 43 |     |         uint256[] calldata gracePeriods
 44 |     |     ) external;
 45 |     | }
 46 |     | 

/opt/scfuzzbench/work/target/src/libraries/AssetMetadataLib.sol
  1 |     | // SPDX-License-Identifier: UNLICENSED
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | import { IERC20Metadata } from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";
  5 |     | 
  6 |     | /// @title AssetMetadataLib
  7 |     | /// @author Superform Labs
  8 |     | /// @notice Library for handling ERC20 metadata operations
  9 |     | library AssetMetadataLib {
 10 |     |     error INVALID_ASSET();
 11 |     | 
 12 |     |     /**
 13 |     |      * @notice Attempts to fetch an asset's decimals
 14 |     |      * @dev A return value of false indicates that the attempt failed in some way
 15 |     |      * @param asset_ The address of the token to query
 16 |     |      * @return ok Boolean indicating if the operation was successful
 17 |     |      * @return assetDecimals The token's decimals if successful, 0 otherwise
 18 |     |      */
 19 | *   |     function tryGetAssetDecimals(address asset_) internal view returns (bool ok, uint8 assetDecimals) {
 20 | *   |         if(asset_.code.length == 0) revert INVALID_ASSET();
 21 |     |         
 22 | *   |         (bool success, bytes memory encodedDecimals) =
 23 | *   |             address(asset_).staticcall(abi.encodeCall(IERC20Metadata.decimals, ()));
 24 | *   |         if (success && encodedDecimals.length >= 32) {
 25 | *   |             uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256));
 26 | *   |             if (returnedDecimals <= type(uint8).max) {
 27 | *   |                 return (true, uint8(returnedDecimals));
 28 |     |             }
 29 |     |         }
 30 | *   |         return (false, 0);
 31 |     |     }
 32 |     | }
 33 |     | 

/opt/scfuzzbench/work/target/src/vendor/standards/ERC7540/IERC7540Vault.sol
   1 |     | // SPDX-License-Identifier: AGPL-3.0-only
   2 |     | pragma solidity >=0.8.0;
   3 |     | 
   4 |     | import { IERC7741 } from "../ERC7741/IERC7741.sol";
   5 |     | 
   6 |     | interface IERC7540Operator {
   7 |     |     /**
   8 |     |      * @dev The event emitted when an operator is set.
   9 |     |      *
  10 |     |      * @param controller The address of the controller.
  11 |     |      * @param operator The address of the operator.
  12 |     |      * @param approved The approval status.
  13 |     |      */
  14 |     |     event OperatorSet(address indexed controller, address indexed operator, bool approved);
  15 |     | 
  16 |     |     /**
  17 |     |      * @dev Sets or removes an operator for the caller.
  18 |     |      *
  19 |     |      * @param operator The address of the operator.
  20 |     |      * @param approved The approval status.
  21 |     |      * @return Whether the call was executed successfully or not
  22 |     |      */
  23 |     |     function setOperator(address operator, bool approved) external returns (bool);
  24 |     | 
  25 |     |     /**
  26 |     |      * @dev Returns `true` if the `operator` is approved as an operator for an `controller`.
  27 |     |      *
  28 |     |      * @param controller The address of the controller.
  29 |     |      * @param operator The address of the operator.
  30 |     |      * @return status The approval status
  31 |     |      */
  32 |     |     function isOperator(address controller, address operator) external view returns (bool status);
  33 |     | }
  34 |     | 
  35 |     | interface IERC7540Deposit is IERC7540Operator {
  36 |     |     event DepositRequest(
  37 |     |         address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
  38 |     |     );
  39 |     |     /**
  40 |     |      * @dev Transfers assets from sender into the Vault and submits a Request for asynchronous deposit.
  41 |     |      *
  42 |     |      * - MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow.
  43 |     |      * - MUST revert if all of assets cannot be requested for deposit.
  44 |     |      * - owner MUST be msg.sender unless some unspecified explicit approval is given by the caller,
  45 |     |      *    approval of ERC-20 tokens from owner to sender is NOT enough.
  46 |     |      *
  47 |     |      * @param assets the amount of deposit assets to transfer from owner
  48 |     |      * @param controller the controller of the request who will be able to operate the request
  49 |     |      * @param owner the source of the deposit assets
  50 |     |      *
  51 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.
  52 |     |      */
  53 |     | 
  54 |     |     function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);
  55 |     | 
  56 |     |     /**
  57 |     |      * @dev Returns the amount of requested assets in Pending state.
  58 |     |      *
  59 |     |      * - MUST NOT include any assets in Claimable state for deposit or mint.
  60 |     |      * - MUST NOT show any variations depending on the caller.
  61 |     |      * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
  62 |     |      */
  63 |     |     function pendingDepositRequest(
  64 |     |         uint256 requestId,
  65 |     |         address controller
  66 |     |     )
  67 |     |         external
  68 |     |         view
  69 |     |         returns (uint256 pendingAssets);
  70 |     | 
  71 |     |     /**
  72 |     |      * @dev Returns the amount of requested assets in Claimable state for the controller to deposit or mint.
  73 |     |      *
  74 |     |      * - MUST NOT include any assets in Pending state.
  75 |     |      * - MUST NOT show any variations depending on the caller.
  76 |     |      * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
  77 |     |      */
  78 |     |     function claimableDepositRequest(
  79 |     |         uint256 requestId,
  80 |     |         address controller
  81 |     |     )
  82 |     |         external
  83 |     |         view
  84 |     |         returns (uint256 claimableAssets);
  85 |     | 
  86 |     |     /**
  87 |     |      * @dev Mints shares Vault shares to receiver by claiming the Request of the controller.
  88 |     |      *
  89 |     |      * - MUST emit the Deposit event.
  90 |     |      * - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
  91 |     |      */
  92 |     |     function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares);
  93 |     | 
  94 |     |     /**
  95 |     |      * @dev Mints exactly shares Vault shares to receiver by claiming the Request of the controller.
  96 |     |      *
  97 |     |      * - MUST emit the Deposit event.
  98 |     |      * - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
  99 |     |      */
 100 |     |     function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets);
 101 |     | }
 102 |     | 
 103 |     | interface IERC7540Redeem is IERC7540Operator {
 104 |     |     event RedeemRequest(
 105 |     |         address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
 106 |     |     );
 107 |     | 
 108 |     |     /**
 109 |     |      * @dev Assumes control of shares from sender into the Vault and submits a Request for asynchronous redeem.
 110 |     |      *
 111 |     |      * - MUST support a redeem Request flow where the control of shares is taken from sender directly
 112 |     |      *   where msg.sender has ERC-20 approval over the shares of owner.
 113 |     |      * - MUST revert if all of shares cannot be requested for redeem.
 114 |     |      *
 115 |     |      * @param shares the amount of shares to be redeemed to transfer from owner
 116 |     |      * @param controller the controller of the request who will be able to operate the request
 117 |     |      * @param owner the source of the shares to be redeemed
 118 |     |      *
 119 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault's share token.
 120 |     |      */
 121 |     |     function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);
 122 |     | 
 123 |     |     /**
 124 |     |      * @dev Returns the amount of requested shares in Pending state.
 125 |     |      *
 126 |     |      * - MUST NOT include any shares in Claimable state for redeem or withdraw.
 127 |     |      * - MUST NOT show any variations depending on the caller.
 128 |     |      * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
 129 |     |      */
 130 |     |     function pendingRedeemRequest(
 131 |     |         uint256 requestId,
 132 |     |         address controller
 133 |     |     )
 134 |     |         external
 135 |     |         view
 136 |     |         returns (uint256 pendingShares);
 137 |     | 
 138 |     |     /**
 139 |     |      * @dev Returns the amount of requested shares in Claimable state for the controller to redeem or withdraw.
 140 |     |      *
 141 |     |      * - MUST NOT include any shares in Pending state for redeem or withdraw.
 142 |     |      * - MUST NOT show any variations depending on the caller.
 143 |     |      * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
 144 |     |      */
 145 |     |     function claimableRedeemRequest(
 146 |     |         uint256 requestId,
 147 |     |         address controller
 148 |     |     )
 149 |     |         external
 150 |     |         view
 151 |     |         returns (uint256 claimableShares);
 152 |     | }
 153 |     | 
 154 |     | interface IERC7540CancelDeposit {
 155 |     |     event CancelDepositRequest(address indexed controller, uint256 indexed requestId, address sender);
 156 |     |     event CancelDepositClaim(
 157 |     |         address indexed receiver, address indexed controller, uint256 indexed requestId, address sender, uint256 assets
 158 |     |     );
 159 |     | 
 160 |     |     /**
 161 |     |      * @dev Submits a Request for cancelling the pending deposit Request
 162 |     |      *
 163 |     |      * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
 164 |     |      *    approval of ERC-20 tokens from controller to sender is NOT enough.
 165 |     |      * - MUST set pendingCancelDepositRequest to `true` for the returned requestId after request
 166 |     |      * - MUST increase claimableCancelDepositRequest for the returned requestId after fulfillment
 167 |     |      * - SHOULD be claimable using `claimCancelDepositRequest`
 168 |     |      * Note: while `pendingCancelDepositRequest` is `true`, `requestDeposit` cannot be called
 169 |     |      */
 170 |     |     function cancelDepositRequest(uint256 requestId, address controller) external;
 171 |     | 
 172 |     |     /**
 173 |     |      * @dev Returns whether the deposit Request is pending cancelation
 174 |     |      *
 175 |     |      * - MUST NOT show any variations depending on the caller.
 176 |     |      */
 177 |     |     function pendingCancelDepositRequest(
 178 |     |         uint256 requestId,
 179 |     |         address controller
 180 |     |     )
 181 |     |         external
 182 |     |         view
 183 |     |         returns (bool isPending);
 184 |     | 
 185 |     |     /**
 186 |     |      * @dev Returns the amount of assets that were canceled from a deposit Request, and can now be claimed.
 187 |     |      *
 188 |     |      * - MUST NOT show any variations depending on the caller.
 189 |     |      */
 190 |     |     function claimableCancelDepositRequest(
 191 |     |         uint256 requestId,
 192 |     |         address controller
 193 |     |     )
 194 |     |         external
 195 |     |         view
 196 |     |         returns (uint256 claimableAssets);
 197 |     | 
 198 |     |     /**
 199 |     |      * @dev Claims the canceled deposit assets, and removes the pending cancelation Request
 200 |     |      *
 201 |     |      * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
 202 |     |      *    approval of ERC-20 tokens from controller to sender is NOT enough.
 203 |     |      * - MUST set pendingCancelDepositRequest to `false` for the returned requestId after request
 204 |     |      * - MUST set claimableCancelDepositRequest to 0 for the returned requestId after fulfillment
 205 |     |      */
 206 |     |     function claimCancelDepositRequest(
 207 |     |         uint256 requestId,
 208 |     |         address receiver,
 209 |     |         address controller
 210 |     |     )
 211 |     |         external
 212 |     |         returns (uint256 assets);
 213 |     | }
 214 |     | 
 215 |     | interface IERC7540CancelRedeem {
 216 |     |     event CancelRedeemRequest(address indexed controller, uint256 indexed requestId, address sender);
 217 |     |     event CancelRedeemClaim(
 218 |     |         address indexed receiver, address indexed controller, uint256 indexed requestId, address sender, uint256 shares
 219 |     |     );
 220 |     | 
 221 |     |     /**
 222 |     |      * @dev Submits a Request for cancelling the pending redeem Request
 223 |     |      *
 224 |     |      * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
 225 |     |      *    approval of ERC-20 tokens from controller to sender is NOT enough.
 226 |     |      * - MUST set pendingCancelRedeemRequest to `true` for the returned requestId after request
 227 |     |      * - MUST increase claimableCancelRedeemRequest for the returned requestId after fulfillment
 228 |     |      * - SHOULD be claimable using `claimCancelRedeemRequest`
 229 |     |      * Note: while `pendingCancelRedeemRequest` is `true`, `requestRedeem` cannot be called
 230 |     |      */
 231 |     |     function cancelRedeemRequest(uint256 requestId, address controller) external;
 232 |     | 
 233 |     |     /**
 234 |     |      * @dev Returns whether the redeem Request is pending cancelation
 235 |     |      *
 236 |     |      * - MUST NOT show any variations depending on the caller.
 237 |     |      */
 238 |     |     function pendingCancelRedeemRequest(uint256 requestId, address controller) external view returns (bool isPending);
 239 |     | 
 240 |     |     /**
 241 |     |      * @dev Returns the amount of shares that were canceled from a redeem Request, and can now be claimed.
 242 |     |      *
 243 |     |      * - MUST NOT show any variations depending on the caller.
 244 |     |      */
 245 |     |     function claimableCancelRedeemRequest(
 246 |     |         uint256 requestId,
 247 |     |         address controller
 248 |     |     )
 249 |     |         external
 250 |     |         view
 251 |     |         returns (uint256 claimableShares);
 252 |     | 
 253 |     |     /**
 254 |     |      * @dev Claims the canceled redeem shares, and removes the pending cancelation Request
 255 |     |      *
 256 |     |      * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
 257 |     |      *    approval of ERC-20 tokens from controller to sender is NOT enough.
 258 |     |      * - MUST set pendingCancelRedeemRequest to `false` for the returned requestId after request
 259 |     |      * - MUST set claimableCancelRedeemRequest to 0 for the returned requestId after fulfillment
 260 |     |      */
 261 |     |     function claimCancelRedeemRequest(
 262 |     |         uint256 requestId,
 263 |     |         address receiver,
 264 |     |         address controller
 265 |     |     )
 266 |     |         external
 267 |     |         returns (uint256 shares);
 268 |     | }
 269 |     | 
 270 |     | /**
 271 |     |  * @title  IERC7540
 272 |     |  * @dev    Fully async ERC7540 implementation according to the standard
 273 |     |  * @dev    Adapted from Centrifuge's IERC7540 implementation
 274 |     |  */
 275 |     | interface IERC7540 is IERC7540Deposit, IERC7540Redeem { }
 276 |     | 
 277 |     | /**
 278 |     |  * @title  IERC7540Vault
 279 |     |  * @dev    This is the specific set of interfaces used by the SuperVaults
 280 |     |  */
 281 |     | interface IERC7540Vault is IERC7540, IERC7741 {
 282 |     |     event DepositClaimable(address indexed controller, uint256 indexed requestId, uint256 assets, uint256 shares);
 283 |     |     event RedeemClaimable(address indexed controller, uint256 indexed requestId, uint256 assets, uint256 shares);
 284 |     | }
 285 |     | 

/opt/scfuzzbench/work/target/src/vendor/standards/ERC7575/IERC7575.sol
   1 |     | // SPDX-License-Identifier: AGPL-3.0-only
   2 |     | pragma solidity >=0.8.0;
   3 |     | 
   4 |     | /**
   5 |     |  * @dev Interface of the ERC165 standard, as defined in the
   6 |     |  * https://eips.ethereum.org/EIPS/eip-165[EIP].
   7 |     |  *
   8 |     |  * Implementers can declare support of contract interfaces, which can then be
   9 |     |  * queried by others.
  10 |     |  */
  11 |     | interface IERC165 {
  12 |     |     /**
  13 |     |      * @dev Returns true if this contract implements the interface defined by
  14 |     |      * `interfaceId`. See the corresponding
  15 |     |      * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
  16 |     |      * to learn more about how these ids are created.
  17 |     |      *
  18 |     |      * This function call must use less than 30 000 gas.
  19 |     |      */
  20 |     |     function supportsInterface(bytes4 interfaceId) external view returns (bool);
  21 |     | }
  22 |     | 
  23 |     | interface IERC7575 is IERC165 {
  24 |     |     event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
  25 |     |     event Withdraw(
  26 |     |         address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
  27 |     |     );
  28 |     | 
  29 |     |     /**
  30 |     |      * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
  31 |     |      *
  32 |     |      * - MUST be an ERC-20 token contract.
  33 |     |      * - MUST NOT revert.
  34 |     |      */
  35 |     |     function asset() external view returns (address assetTokenAddress);
  36 |     | 
  37 |     |     /**
  38 |     |      * @dev Returns the address of the share token
  39 |     |      *
  40 |     |      * - MUST be an ERC-20 token contract.
  41 |     |      * - MUST NOT revert.
  42 |     |      */
  43 |     |     function share() external view returns (address shareTokenAddress);
  44 |     | 
  45 |     |     /**
  46 |     |      * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
  47 |     |      * scenario where all the conditions are met.
  48 |     |      *
  49 |     |      * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
  50 |     |      * - MUST NOT show any variations depending on the caller.
  51 |     |      * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
  52 |     |      * - MUST NOT revert.
  53 |     |      *
  54 |     |      * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
  55 |     |      * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
  56 |     |      * from.
  57 |     |      */
  58 |     |     function convertToShares(uint256 assets) external view returns (uint256 shares);
  59 |     | 
  60 |     |     /**
  61 |     |      * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
  62 |     |      * scenario where all the conditions are met.
  63 |     |      *
  64 |     |      * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
  65 |     |      * - MUST NOT show any variations depending on the caller.
  66 |     |      * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
  67 |     |      * - MUST NOT revert.
  68 |     |      *
  69 |     |      * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
  70 |     |      * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
  71 |     |      * from.
  72 |     |      */
  73 |     |     function convertToAssets(uint256 shares) external view returns (uint256 assets);
  74 |     | 
  75 |     |     /**
  76 |     |      * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
  77 |     |      *
  78 |     |      * - SHOULD include any compounding that occurs from yield.
  79 |     |      * - MUST be inclusive of any fees that are charged against assets in the Vault.
  80 |     |      * - MUST NOT revert.
  81 |     |      */
  82 |     |     function totalAssets() external view returns (uint256 totalManagedAssets);
  83 |     | 
  84 |     |     /**
  85 |     |      * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
  86 |     |      * through a deposit call.
  87 |     |      *
  88 |     |      * - MUST return a limited value if receiver is subject to some deposit limit.
  89 |     |      * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
  90 |     |      * - MUST NOT revert.
  91 |     |      */
  92 |     |     function maxDeposit(address receiver) external view returns (uint256 maxAssets);
  93 |     | 
  94 |     |     /**
  95 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
  96 |     |      * current on-chain conditions.
  97 |     |      *
  98 |     |      * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
  99 |     |      *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
 100 |     |      *   in the same transaction.
 101 |     |      * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
 102 |     |      *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
 103 |     |      * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
 104 |     |      * - MUST NOT revert.
 105 |     |      *
 106 |     |      * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
 107 |     |      * share price or some other type of condition, meaning the depositor will lose assets by depositing.
 108 |     |      */
 109 |     |     function previewDeposit(uint256 assets) external view returns (uint256 shares);
 110 |     | 
 111 |     |     /**
 112 |     |      * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
 113 |     |      *
 114 |     |      * - MUST emit the Deposit event.
 115 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
 116 |     |      *   deposit execution, and are accounted for during deposit.
 117 |     |      * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
 118 |     |      *   approving enough underlying tokens to the Vault contract, etc).
 119 |     |      *
 120 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
 121 |     |      */
 122 |     |     function deposit(uint256 assets, address receiver) external returns (uint256 shares);
 123 |     | 
 124 |     |     /**
 125 |     |      * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
 126 |     |      * - MUST return a limited value if receiver is subject to some mint limit.
 127 |     |      * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
 128 |     |      * - MUST NOT revert.
 129 |     |      */
 130 |     |     function maxMint(address receiver) external view returns (uint256 maxShares);
 131 |     | 
 132 |     |     /**
 133 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
 134 |     |      * current on-chain conditions.
 135 |     |      *
 136 |     |      * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
 137 |     |      *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
 138 |     |      *   same transaction.
 139 |     |      * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
 140 |     |      *   would be accepted, regardless if the user has enough tokens approved, etc.
 141 |     |      * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
 142 |     |      * - MUST NOT revert.
 143 |     |      *
 144 |     |      * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
 145 |     |      * share price or some other type of condition, meaning the depositor will lose assets by minting.
 146 |     |      */
 147 |     |     function previewMint(uint256 shares) external view returns (uint256 assets);
 148 |     | 
 149 |     |     /**
 150 |     |      * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
 151 |     |      *
 152 |     |      * - MUST emit the Deposit event.
 153 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
 154 |     |      *   execution, and are accounted for during mint.
 155 |     |      * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
 156 |     |      *   approving enough underlying tokens to the Vault contract, etc).
 157 |     |      *
 158 |     |      * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
 159 |     |      */
 160 |     |     function mint(uint256 shares, address receiver) external returns (uint256 assets);
 161 |     | 
 162 |     |     /**
 163 |     |      * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
 164 |     |      * Vault, through a withdraw call.
 165 |     |      *
 166 |     |      * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
 167 |     |      * - MUST NOT revert.
 168 |     |      */
 169 |     |     function maxWithdraw(address owner) external view returns (uint256 maxAssets);
 170 |     | 
 171 |     |     /**
 172 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
 173 |     |      * given current on-chain conditions.
 174 |     |      *
 175 |     |      * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
 176 |     |      *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
 177 |     |      *   called
 178 |     |      *   in the same transaction.
 179 |     |      * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
 180 |     |      *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
 181 |     |      * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
 182 |     |      * - MUST NOT revert.
 183 |     |      *
 184 |     |      * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
 185 |     |      * share price or some other type of condition, meaning the depositor will lose assets by depositing.
 186 |     |      */
 187 |     |     function previewWithdraw(uint256 assets) external view returns (uint256 shares);
 188 |     | 
 189 |     |     /**
 190 |     |      * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
 191 |     |      *
 192 |     |      * - MUST emit the Withdraw event.
 193 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
 194 |     |      *   withdraw execution, and are accounted for during withdraw.
 195 |     |      * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
 196 |     |      *   not having enough shares, etc).
 197 |     |      *
 198 |     |      * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
 199 |     |      * Those methods should be performed separately.
 200 |     |      */
 201 |     |     function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
 202 |     | 
 203 |     |     /**
 204 |     |      * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
 205 |     |      * through a redeem call.
 206 |     |      *
 207 |     |      * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
 208 |     |      * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
 209 |     |      * - MUST NOT revert.
 210 |     |      */
 211 |     |     function maxRedeem(address owner) external view returns (uint256 maxShares);
 212 |     | 
 213 |     |     /**
 214 |     |      * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
 215 |     |      * given current on-chain conditions.
 216 |     |      *
 217 |     |      * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
 218 |     |      *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
 219 |     |      *   same transaction.
 220 |     |      * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
 221 |     |      *   redemption would be accepted, regardless if the user has enough shares, etc.
 222 |     |      * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
 223 |     |      * - MUST NOT revert.
 224 |     |      *
 225 |     |      * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
 226 |     |      * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
 227 |     |      */
 228 |     |     function previewRedeem(uint256 shares) external view returns (uint256 assets);
 229 |     | 
 230 |     |     /**
 231 |     |      * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
 232 |     |      *
 233 |     |      * - MUST emit the Withdraw event.
 234 |     |      * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
 235 |     |      *   redeem execution, and are accounted for during redeem.
 236 |     |      * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
 237 |     |      *   not having enough shares, etc).
 238 |     |      *
 239 |     |      * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
 240 |     |      * Those methods should be performed separately.
 241 |     |      */
 242 |     |     function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
 243 |     | }
 244 |     | 

/opt/scfuzzbench/work/target/src/vendor/standards/ERC7741/IERC7741.sol
  1 |     | // SPDX-License-Identifier: AGPL-3.0-only
  2 |     | pragma solidity >=0.8.0;
  3 |     | 
  4 |     | interface IERC7741 {
  5 |     |     /**
  6 |     |      * @dev Grants or revokes permissions for `operator` to manage Requests on behalf of the
  7 |     |      *      `msg.sender`, using an [EIP-712](./eip-712.md) signature.
  8 |     |      */
  9 |     |     function authorizeOperator(
 10 |     |         address controller,
 11 |     |         address operator,
 12 |     |         bool approved,
 13 |     |         bytes32 nonce,
 14 |     |         uint256 deadline,
 15 |     |         bytes memory signature
 16 |     |     )
 17 |     |         external
 18 |     |         returns (bool);
 19 |     | 
 20 |     |     /**
 21 |     |      * @dev Revokes the given `nonce` for `msg.sender` as the `owner`.
 22 |     |      */
 23 |     |     function invalidateNonce(bytes32 nonce) external;
 24 |     | 
 25 |     |     /**
 26 |     |      * @dev Returns whether the given `nonce` has been used for the `controller`.
 27 |     |      */
 28 |     |     function authorizations(address controller, bytes32 nonce) external view returns (bool used);
 29 |     | 
 30 |     |     /**
 31 |     |      * @dev Returns the `DOMAIN_SEPARATOR` as defined according to EIP-712. The `DOMAIN_SEPARATOR
 32 |     |      *      should be unique to the contract and chain to prevent replay attacks from other domains,
 33 |     |      *      and satisfy the requirements of EIP-712, but is otherwise unconstrained.
 34 |     |      */
 35 |     |     function DOMAIN_SEPARATOR() external view returns (bytes32);
 36 |     | }
 37 |     | 

/opt/scfuzzbench/work/target/test/mocks/MockYieldSourceOracle.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity ^0.8.30;
   3 |     | 
   4 |     | import { IYieldSourceOracle } from "@superform-v2-core/src/interfaces/accounting/IYieldSourceOracle.sol";
   5 |     | 
   6 |     | // Mock YieldSourceOracle implementation for testing
   7 |     | contract MockYieldSourceOracle is IYieldSourceOracle {
   8 |     |     uint256 public pricePerShare;
   9 |     |     uint256 public tvl;
  10 |     |     uint256 public tvlByOwner;
  11 |     |     bool public validity;
  12 |     |     mapping(address => bool) public validAssetMap;
  13 |     | 
  14 |     |     constructor(uint256 _pricePerShare, uint256 _tvl, uint256 _tvlByOwner, bool _validity) {
  15 |     |         pricePerShare = _pricePerShare;
  16 |     |         tvl = _tvl;
  17 |     |         tvlByOwner = _tvlByOwner;
  18 |     |         validity = _validity;
  19 |     |     }
  20 |     | 
  21 |     |     function setPricePerShare(uint256 _pricePerShare) external {
  22 |     |         pricePerShare = _pricePerShare;
  23 |     |     }
  24 |     | 
  25 |     |     function setTVL(uint256 _tvl) external {
  26 |     |         tvl = _tvl;
  27 |     |     }
  28 |     | 
  29 |     |     function setTVLByOwner(uint256 _tvlByOwner) external {
  30 |     |         tvlByOwner = _tvlByOwner;
  31 |     |     }
  32 |     | 
  33 |     |     function setValidity(bool _validity) external {
  34 |     |         validity = _validity;
  35 |     |     }
  36 |     | 
  37 |     |     function setValidAsset(address asset, bool isValid) external {
  38 |     |         validAssetMap[asset] = isValid;
  39 |     |     }
  40 |     | 
  41 |     |     function decimals(address) external pure returns (uint8) {
  42 |     |         return 18;
  43 |     |     }
  44 |     | 
  45 |     |     function getShareOutput(address, address, uint256 assetsIn) external pure returns (uint256) {
  46 |     |         return assetsIn;
  47 |     |     }
  48 |     | 
  49 |     |     function getAssetOutput(address, address, uint256 sharesIn) public pure returns (uint256) {
  50 |     |         return sharesIn;
  51 |     |     }
  52 |     | 
  53 |     |     function getAssetOutputWithFees(
  54 |     |         bytes32,
  55 |     |         address,
  56 |     |         address,
  57 |     |         address,
  58 |     |         uint256 sharesIn
  59 |     |     )
  60 |     |         public
  61 |     |         pure
  62 |     |         returns (uint256)
  63 |     |     {
  64 |     |         return sharesIn;
  65 |     |     }
  66 |     | 
  67 |     |     function getBalanceOfOwner(address, address) external view returns (uint256) {
  68 |     |         return tvlByOwner;
  69 |     |     }
  70 |     | 
  71 |     |     function getPricePerShare(address) external view returns (uint256) {
  72 |     |         return pricePerShare;
  73 |     |     }
  74 |     | 
  75 |     |     function getTVLByOwnerOfShares(address, address) external view returns (uint256) {
  76 |     |         return tvlByOwner;
  77 |     |     }
  78 |     | 
  79 |     |     function getTVL(address) external view returns (uint256) {
  80 |     |         return tvl;
  81 |     |     }
  82 |     | 
  83 |     |     function getPricePerShareMultiple(address[] memory) external view returns (uint256[] memory) {
  84 |     |         uint256[] memory prices = new uint256[](1);
  85 |     |         prices[0] = pricePerShare;
  86 |     |         return prices;
  87 |     |     }
  88 |     | 
  89 |     |     function getTVLByOwnerOfSharesMultiple(
  90 |     |         address[] memory yieldSources,
  91 |     |         address[][] memory
  92 |     |     )
  93 |     |         external
  94 |     |         view
  95 |     |         returns (uint256[][] memory)
  96 |     |     {
  97 |     |         uint256[][] memory result = new uint256[][](yieldSources.length);
  98 |     |         for (uint256 i = 0; i < yieldSources.length; i++) {
  99 |     |             result[i] = new uint256[](1);
 100 |     |             result[i][0] = tvlByOwner;
 101 |     |         }
 102 |     |         return result;
 103 |     |     }
 104 |     | 
 105 |     |     function getTVLMultiple(address[] memory) external view returns (uint256[] memory) {
 106 |     |         uint256[] memory tvls = new uint256[](1);
 107 |     |         tvls[0] = tvl;
 108 |     |         return tvls;
 109 |     |     }
 110 |     | 
 111 |     |     function isValidUnderlyingAsset(address, address asset) external view returns (bool) {
 112 |     |         return validAssetMap[asset];
 113 |     |     }
 114 |     | 
 115 |     |     function isValidUnderlyingAssets(address[] memory, address[] memory) external view returns (bool[] memory) {
 116 |     |         bool[] memory validities = new bool[](1);
 117 |     |         validities[0] = validity;
 118 |     |         return validities;
 119 |     |     }
 120 |     | }
 121 |     | 

/opt/scfuzzbench/work/target/test/recon/BeforeAfter.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   5 |     | import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
   6 |     | import {MockERC20} from "@recon/MockERC20.sol";
   7 |     | 
   8 |     | import {ISuperVaultStrategy} from "src/interfaces/SuperVault/ISuperVaultStrategy.sol";
   9 |     | 
  10 |     | import {Setup} from "./Setup.sol";
  11 |     | 
  12 |     | enum OpType {
  13 |     |     DEFAULT,
  14 |     |     ADD,
  15 |     |     REMOVE,
  16 |     |     FULFILL,
  17 |     |     REQUEST,
  18 |     |     TRANSFER,
  19 |     |     CANCEL
  20 |     | }
  21 |     | 
  22 |     | // ghost variables for tracking state variable values before and after function calls
  23 |     | abstract contract BeforeAfter is Setup {
  24 |     |     struct Vars {
  25 |     |         mapping(address user => uint256 pendingAsAssets) pendingUserAssets;
  26 |     |         mapping(address user => uint256 claimableAsAssets) claimableUserAssets;
  27 |     |         mapping(address user => ISuperVaultStrategy.SuperVaultState) state;
  28 |     |         mapping(address user => uint256 shares) superVaultShares;
  29 |     |         uint256 oraclePPS;
  30 |     |         uint256 naivePPS;
  31 |     |         uint256 summedTotalShares;
  32 |     |         uint256 summedAccumulatorShares;
  33 |     |         uint256 summedAccumulatorCostBasis;
  34 |     |         uint256 summedTotalAssets;
  35 |     |         uint256 strategyAssetBalance;
  36 |     |         uint256 summedPendingRedeem;
  37 |     |     }
  38 |     | 
  39 |     |     Vars internal _before;
  40 |     |     Vars internal _after;
  41 |     |     OpType internal _currentOp;
  42 |     | 
  43 |     |     modifier updateGhosts() {
  44 | *   |         _currentOp = OpType.DEFAULT;
  45 | *   |         __before();
  46 |     |         _;
  47 | *   |         __after();
  48 |     |     }
  49 |     | 
  50 |     |     modifier updateGhostsWithOpType(OpType op) {
  51 | *   |         _currentOp = op;
  52 | *   |         __before();
  53 |     |         _;
  54 | *   |         __after();
  55 |     |     }
  56 |     | 
  57 | *   |     function __before() internal {
  58 | *   |         (
  59 | *   |             _before.summedAccumulatorShares,
  60 | *   |             _before.summedAccumulatorCostBasis
  61 | *   |         ) = _sumSuperVaultValues();
  62 | *   |         _before.naivePPS = _calculateNaivePPS();
  63 | *   |         _before.summedTotalShares = _sumTotalShares();
  64 | *   |         _before.summedTotalAssets = _sumStrategyAssets();
  65 | *   |         _before.summedPendingRedeem = _sumRequestedRedemptions();
  66 |     | 
  67 | *   |         _before.pendingUserAssets[_getActor()] = _getPendingAsAssets();
  68 | *   |         _before.claimableUserAssets[_getActor()] = _getClaimableAsAssets();
  69 | *   |         _before.state[_getActor()] = superVaultStrategy.getSuperVaultState(
  70 | *   |             _getActor()
  71 |     |         );
  72 | *   |         _before.superVaultShares[_getActor()] = superVault.balanceOf(
  73 | *   |             _getActor()
  74 |     |         );
  75 |     | 
  76 | *   |         _before.strategyAssetBalance = MockERC20(superVault.asset()).balanceOf(
  77 | *   |             address(superVaultStrategy)
  78 |     |         );
  79 | *   |         _before.oraclePPS = superVaultAggregator.getPPS(
  80 | *   |             address(superVaultStrategy)
  81 |     |         );
  82 |     |     }
  83 |     | 
  84 | *   |     function __after() internal {
  85 | *   |         (
  86 | *   |             _after.summedAccumulatorShares,
  87 | *   |             _after.summedAccumulatorCostBasis
  88 | *   |         ) = _sumSuperVaultValues();
  89 | *   |         _after.naivePPS = _calculateNaivePPS();
  90 | *   |         _after.summedTotalShares = _sumTotalShares();
  91 | *   |         _after.summedTotalAssets = _sumStrategyAssets();
  92 | *   |         _after.summedPendingRedeem = _sumRequestedRedemptions();
  93 |     | 
  94 | *   |         _after.pendingUserAssets[_getActor()] = _getPendingAsAssets();
  95 | *   |         _after.claimableUserAssets[_getActor()] = _getClaimableAsAssets();
  96 | *   |         _after.state[_getActor()] = superVaultStrategy.getSuperVaultState(
  97 | *   |             _getActor()
  98 |     |         );
  99 | *   |         _after.superVaultShares[_getActor()] = superVault.balanceOf(
 100 | *   |             _getActor()
 101 |     |         );
 102 |     | 
 103 | *   |         _after.strategyAssetBalance = MockERC20(superVault.asset()).balanceOf(
 104 | *   |             address(superVaultStrategy)
 105 |     |         );
 106 | *   |         _after.oraclePPS = superVaultAggregator.getPPS(
 107 | *   |             address(superVaultStrategy)
 108 |     |         );
 109 |     |     }
 110 |     | 
 111 |     |     // Helpers
 112 |     | 
 113 |     |     /// @dev total shares in the system is the sum of shares in the escrow and held by all users
 114 | *   |     function _sumTotalShares() internal returns (uint256) {
 115 | *   |         address[] memory actors = _getActors();
 116 | *   |         uint256 totalShares;
 117 |     | 
 118 | *   |         totalShares += superVault.balanceOf(address(superVaultEscrow));
 119 | *   |         for (uint256 i; i < actors.length; i++) {
 120 | *   |             totalShares += superVault.balanceOf(actors[i]);
 121 |     |         }
 122 |     | 
 123 |     |         return totalShares;
 124 |     |     }
 125 |     | 
 126 |     |     /// @notice Calculates the naive price per share by summing all assets across strategy and yield sources
 127 |     |     /// @dev inspired by the share price calculation from BaseSuperVaultTest::_updateSuperVaultPPS
 128 |     |     /// @return naivePPS The calculated price per share (scaled by 1e18)
 129 | *   |     function _calculateNaivePPS() internal returns (uint256 naivePPS) {
 130 |     |         // Get total supply of SuperVault shares
 131 | *   |         uint256 totalSupply = superVault.totalSupply();
 132 |     | 
 133 |     |         // If no shares exist, PPS is 0
 134 | *   |         if (totalSupply == 0) {
 135 | *   |             return 0;
 136 |     |         }
 137 |     | 
 138 |     |         // Calculate total assets across all locations
 139 | *   |         uint256 totalAssets = _sumStrategyAssets();
 140 |     | 
 141 |     |         // Calculate naive PPS: (totalAssets * PRECISION) / totalSupply
 142 |     |         // Using 1e18 as precision to match the system's PPS_DECIMALS
 143 | *   |         naivePPS = (totalAssets * superVault.PRECISION()) / totalSupply;
 144 |     | 
 145 |     |         return naivePPS;
 146 |     |     }
 147 |     | 
 148 | *r  |     function _sumStrategyAssets() public view returns (uint256) {
 149 |     |         // Get the underlying asset
 150 | *   |         address asset = superVault.asset();
 151 |     | 
 152 | *   |         uint256 totalAssets;
 153 |     |         // 1. Assets held directly in SuperVaultStrategy
 154 | *   |         totalAssets += IERC20(asset).balanceOf(address(superVaultStrategy));
 155 |     | 
 156 |     |         // 2. Loop through all yield sources and sum underlying asset balances
 157 | *   |         address[] memory yieldSources = _getYieldSources();
 158 | *   |         for (uint256 i = 0; i < yieldSources.length; i++) {
 159 | *   |             if (yieldSources[i] != address(0)) {
 160 |     |                 // Get the underlying asset balance held in each yield source
 161 | *   |                 totalAssets += IERC20(asset).balanceOf(yieldSources[i]);
 162 |     |             }
 163 |     |         }
 164 |     | 
 165 | *   |         return totalAssets;
 166 |     |     }
 167 |     | 
 168 | *   |     function _sumSuperVaultValues()
 169 |     |         internal
 170 |     |         view
 171 | *   |         returns (uint256 sumAccumulatorShares, uint256 sumAccumulatorCostBasis)
 172 | *   |     {
 173 | *   |         address[] memory actors = _getActors();
 174 |     | 
 175 | *   |         for (uint256 i; i < actors.length; i++) {
 176 | *   |             sumAccumulatorShares += superVaultStrategy
 177 | *   |                 .getSuperVaultState(actors[i])
 178 |     |                 .accumulatorShares;
 179 | *   |             sumAccumulatorCostBasis += superVaultStrategy
 180 | *   |                 .getSuperVaultState(actors[i])
 181 |     |                 .accumulatorCostBasis;
 182 |     |         }
 183 |     |     }
 184 |     | 
 185 | *   |     function _sumRequestedRedemptions() internal returns (uint256) {
 186 | *   |         address[] memory actors = _getActors();
 187 | *   |         uint256 totalRequested;
 188 | *   |         for (uint256 i; i < actors.length; i++) {
 189 | *   |             totalRequested += superVault.pendingRedeemRequest(0, actors[i]);
 190 |     |         }
 191 |     | 
 192 |     |         return totalRequested;
 193 |     |     }
 194 |     | 
 195 | *   |     function _getPendingAsAssets() internal returns (uint256) {
 196 | *   |         uint256 pendingRedemptions = superVault.pendingRedeemRequest(
 197 |     |             0,
 198 | *   |             _getActor()
 199 |     |         );
 200 | *   |         uint256 pendingRedemptionsAsAssets = superVault.convertToAssets(
 201 |     |             pendingRedemptions
 202 |     |         );
 203 |     | 
 204 |     |         return pendingRedemptionsAsAssets;
 205 |     |     }
 206 |     | 
 207 | *   |     function _getClaimableAsAssets() internal returns (uint256) {
 208 | *   |         uint256 claimableRedemptions = superVault.claimableRedeemRequest(
 209 |     |             0,
 210 | *   |             _getActor()
 211 |     |         );
 212 |     |         uint256 claimableRedemptionsAsAssets = superVault.convertToAssets(
 213 |     |             claimableRedemptions
 214 |     |         );
 215 |     | 
 216 |     |         return claimableRedemptionsAsAssets;
 217 |     |     }
 218 |     | }
 219 |     | 

/opt/scfuzzbench/work/target/test/recon/CryticTester.sol
  1 |     | // SPDX-License-Identifier: GPL-2.0
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | import {CryticAsserts} from "@chimera/CryticAsserts.sol";
  5 |     | 
  6 |     | import {TargetFunctions} from "./TargetFunctions.sol";
  7 |     | 
  8 |     | // echidna test/recon/CryticTester.sol --contract CryticTester --config echidna.yaml --format text --test-limit 1000000 --disable-slither
  9 |     | // medusa fuzz
 10 | *   | contract CryticTester is TargetFunctions, CryticAsserts {
 11 |     |     constructor() payable {
 12 | *   |         setup();
 13 |     |     }
 14 |     | }
 15 |     | 

/opt/scfuzzbench/work/target/test/recon/Properties.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {Asserts} from "@chimera/Asserts.sol";
   5 |     | import {MockERC20} from "@recon/MockERC20.sol";
   6 |     | import {vm} from "@chimera/Hevm.sol";
   7 |     | import {ERC7540Properties} from "@properties-7540/ERC7540Properties.sol";
   8 |     | import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
   9 |     | 
  10 |     | import {ISuperVaultStrategy} from "src/interfaces/SuperVault/ISuperVaultStrategy.sol";
  11 |     | 
  12 |     | import {OpType} from "test/recon/BeforeAfter.sol";
  13 |     | import {BeforeAfter} from "./BeforeAfter.sol";
  14 |     | 
  15 |     | abstract contract Properties is BeforeAfter, Asserts, ERC7540Properties {
  16 |     |     using Math for uint256;
  17 | *   |     uint256 internal TOLERANCE = 10;
  18 |     | 
  19 |     |     // `!!!`-prefixed reasons are load-bearing for cross-fuzzer bug dedup in the analysis
  20 |     |     // pipeline. Handler assertion failures surface natively on every fuzzer: as Panic(0x01)
  21 |     |     // under echidna/medusa/recon and as recorded assertion failures under Foundry
  22 |     |     // (`assertions_revert = false`, upstream handler-bug reporting).
  23 |     |     string constant ASSERTION_REDEEM_MAX_REDEEM_SHOULD_NOT_REVERT =
  24 |     |         "!!! redeeming maxRedeem should not revert";
  25 |     |     string constant ASSERTION_WITHDRAW_MAX_WITHDRAW_SHOULD_NOT_REVERT =
  26 |     |         "!!! withdraw of maxWithdraw should not revert";
  27 |     |     string constant ASSERTION_PREVIEW_DEPOSIT_EQUIVALENCE =
  28 |     |         "!!! previewDeposit and deposit equivalence";
  29 |     |     string constant ASSERTION_PREVIEW_MINT_EQUIVALENCE =
  30 |     |         "!!! previewMint and mint equivalence";
  31 |     |     string constant ASSERTION_MINT_REDEEM_SYMMETRICAL =
  32 |     |         "!!! user loses assets in mint/redeem flow";
  33 |     |     string constant ASSERTION_DEPOSIT_WITHDRAW_SYMMETRICAL =
  34 |     |         "!!! user loses assets in deposit/withdraw flow";
  35 |     |     string constant ASSERTION_MAX_REDEEM_RESETS_AFTER_FULL_REDEMPTION =
  36 |     |         "!!! maxRedeem should be reset to 0 after full redemption";
  37 |     |     string constant ASSERTION_MAX_WITHDRAW_RESETS_AFTER_FULL_WITHDRAWAL =
  38 |     |         "!!! maxWithdraw should be reset to 0 after full withdrawal";
  39 |     |     string constant ASSERTION_FULFILL_DOESNT_OVER_REDEEM_MULTIPLE_ACTORS =
  40 |     |         "!!! total shares redeemed must not exceed sum of requested shares";
  41 |     |     string constant ASSERTION_PRIMARY_MANAGER_ALWAYS_CHANGEABLE =
  42 |     |         "!!! Primary manager should always be changeable if not paused";
  43 |     |     string constant ASSERTION_ALL_USERS_CAN_WITHDRAW_WHEN_UNPAUSED =
  44 |     |         "!!! users should always be able to withdraw unless the system is paused";
  45 |     |     string constant ASSERTION_CANCEL_REDEEM_PENDING_REQUEST_ZERO =
  46 |     |         "!!! pendingRedeemRequests should be 0 after cancelling a redemption";
  47 |     |     string constant ASSERTION_CANCEL_REDEEM_AVG_REQUEST_PPS_ZERO =
  48 |     |         "!!! averageRequestPPS should be 0 after cancelling a redemption";
  49 |     |     string constant ASSERTION_CANCEL_REDEEM_NO_OVERPAY =
  50 |     |         "!!! user should not receive more than convertToAssets(pendingRedeemRequest) after cancelRedeem";
  51 |     |     string constant ASSERTION_PREVIEW_DEPOSIT_MATCHES_EXECUTION =
  52 |     |         "!!! previewDeposit returns the correct amount compared to executing a deposit";
  53 |     |     string constant ASSERTION_PREVIEW_MINT_MATCHES_EXECUTION =
  54 |     |         "!!! previewMint returns the correct amount compared to executing a mint";
  55 |     |     string constant ASSERTION_TRANSFER_SHARES_CONSERVED =
  56 |     |         "!!! shares are lost on transfer";
  57 |     |     string constant ASSERTION_TRANSFER_COST_BASIS_CONSERVED =
  58 |     |         "!!! cost basis is lost on transfer";
  59 |     |     string constant ASSERTION_REDEEM_SHOULD_NOT_REVERT_INVALID_REDEEM_CLAIM =
  60 |     |         "!!! Claiming redemptions should never revert with INVALID_REDEEM_CLAIM";
  61 |     |     string constant ASSERTION_UPDATE_SHOULD_NOT_REVERT_TRANSFER =
  62 |     |         "!!! _update should never revert in transfer";
  63 |     |     string constant ASSERTION_UPDATE_SHOULD_NOT_REVERT_TRANSFER_FROM =
  64 |     |         "!!! _update should never revert in transferFrom";
  65 |     |     string constant ASSERTION_STRATEGY_NO_LOSS_ON_FULFILLMENT =
  66 |     |         "!!! strategy incurs loss on fulfillment";
  67 |     |     string constant ASSERTION_GLOBAL_PREVIEW_EQUIVALENCE_FROM_SHARES =
  68 |     |         "!!! previewMint and previewDeposit equivalence (from shares)";
  69 |     |     string constant ASSERTION_GLOBAL_PREVIEW_EQUIVALENCE_FROM_ASSETS =
  70 |     |         "!!! previewMint and previewDeposit equivalence (from assets)";
  71 |     |     string constant ASSERTION_GLOBAL_PREVIEW_MINT_GTE_CONVERT_TO_ASSETS =
  72 |     |         "!!! previewMint is >= convertToAssets";
  73 |     |     string constant ASSERTION_GLOBAL_CONVERT_TO_SHARES_GTE_PREVIEW_DEPOSIT =
  74 |     |         "!!! convertToShares is >= previewDepositShares (equivalent without fees)";
  75 |     |     string constant ASSERTION_ERC7540_4_DEPOSIT =
  76 |     |         "!!! ERC7540-4: deposit with more than max should revert";
  77 |     |     string constant ASSERTION_ERC7540_4_MINT =
  78 |     |         "!!! ERC7540-4: mint with more than max should revert";
  79 |     |     string constant ASSERTION_ERC7540_4_WITHDRAW =
  80 |     |         "!!! ERC7540-4: withdraw with more than max should revert";
  81 |     |     string constant ASSERTION_ERC7540_4_REDEEM =
  82 |     |         "!!! ERC7540-4: redeem with more than max should revert";
  83 |     |     string constant ASSERTION_ERC7540_5 =
  84 |     |         "!!! ERC7540-5: requestRedeem should revert if insufficient share balance";
  85 |     |     string constant ASSERTION_ERC7540_7_WITHDRAW =
  86 |     |         "!!! ERC7540-7: withdraw should not revert when amount <= max";
  87 |     |     string constant ASSERTION_ERC7540_7_REDEEM =
  88 |     |         "!!! ERC7540-7: redeem should not revert when amount <= max";
  89 |     |     string constant ASSERTION_CANARY =
  90 |     |         "!!! canary assertion";
  91 |     |     string constant INVARIANT_CANARY_GLOBAL_INVARIANT_FAILURE =
  92 |     |         "Canary invariant";
  93 |     | 
  94 |     |     /// @dev Property: oracle PPS doesn't change on deposit/mint/redeem/withdraw
  95 | *r  |     function invariant_oraclePPSDoesntChangeOnAddOrRemove() public returns (bool) {
  96 | *   |         if (_currentOp == OpType.ADD || _currentOp == OpType.REMOVE) {
  97 | *   |             eq(
  98 | *   |                 _before.oraclePPS,
  99 | *   |                 _after.oraclePPS,
 100 |     |                 "deposit/withdrawal changes oracle PPS"
 101 |     |             );
 102 |     |         }
 103 |     |         return true;
 104 |     |     }
 105 |     | 
 106 |     |     /// @dev Property: naive PPS doesn't change on deposit/mint
 107 |     |     // NOTE: removed because it's expected behavior that fulfillment burns shares but doesn't transfer assets to users so would change the naively calculated price
 108 |     |     // function property_naivePPSDoesntChangeOnDepositOrMint() public {
 109 |     |     //     if (
 110 |     |     //         (_currentOp == OpType.ADD) && _before.naivePPS != 0 // price starts as zero when no shares minted
 111 |     |     //     ) {
 112 |     |     //         gte(
 113 |     |     //             _after.naivePPS,
 114 |     |     //             _before.naivePPS,
 115 |     |     //             "deposit/mint cannot decrease naive PPS"
 116 |     |     //         );
 117 |     |     //     }
 118 |     |     // }
 119 |     | 
 120 |     |     /// @dev Property: naive PPS doesn't change on redeem/withdraw
 121 |     |     // NOTE: removed because it's expected behavior that fulfillment burns shares but doesn't transfer assets to users so would change the naively calculated price
 122 |     |     // function property_naivePPSDoesntChangeOnRedeemOrWithdraw() public {
 123 |     |     //     if (
 124 |     |     //         (_currentOp == OpType.REMOVE) && _before.naivePPS != 0 // price starts as zero when no shares minted
 125 |     |     //     ) {
 126 |     |     //         gte(
 127 |     |     //             _after.naivePPS,
 128 |     |     //             _before.naivePPS,
 129 |     |     //             "redeem/withdraw cannot decrease naive PPS"
 130 |     |     //         );
 131 |     |     //     }
 132 |     |     // }
 133 |     | 
 134 |     |     /// @dev Property: fulfillRedeemRequest doesn't change naive PPS
 135 |     |     // NOTE: removed because it's expected behavior that fulfillment burns shares but doesn't transfer assets to users so would change the naively calculated price
 136 |     |     // function property_naivePPSDoesntChangeOnRedeem() public {
 137 |     |     //     if (_currentOp == OpType.FULFILL) {
 138 |     |     //         eq(
 139 |     |     //             _before.naivePPS,
 140 |     |     //             _after.naivePPS,
 141 |     |     //             "fulfilling redemption changes naive PPS"
 142 |     |     //         );
 143 |     |     //     }
 144 |     |     // }
 145 |     | 
 146 |     |     /// @dev Property: maxRedeem and maxWithdraw should always be equivalent
 147 | *r  |     function invariant_maxRedeemMaxWithdrawSymmetry() public returns (bool) {
 148 | *   |         uint256 maxWithdraw = superVault.maxWithdraw(_getActor());
 149 |     |         // convertToShares uses current price instead of avg from fulfillment
 150 | *   |         uint256 withdrawPrice = superVaultStrategy.getAverageWithdrawPrice(
 151 | *   |             _getActor()
 152 |     |         );
 153 | *   |         uint256 maxWithdrawAsShares = maxWithdraw.mulDiv(
 154 | *   |             superVault.PRECISION(),
 155 | *   |             withdrawPrice,
 156 | *   |             Math.Rounding.Floor
 157 |     |         );
 158 |     | 
 159 | *   |         uint256 maxRedeem = superVault.maxRedeem(_getActor());
 160 |     | 
 161 | *   |         eq(maxWithdrawAsShares, maxRedeem, "maxWithdrawAsShares != maxRedeem");
 162 | *   |         return true;
 163 |     |     }
 164 |     | 
 165 |     |     /// @dev Property: requestRedeem should never reduce SuperVault shares
 166 | *r  |     function invariant_totalSharesDontDecreaseOnRedemptionRequest() public returns (bool) {
 167 | *   |         if (_currentOp == OpType.REQUEST) {
 168 | *   |             eq(
 169 | *   |                 _before.summedTotalShares,
 170 | *   |                 _after.summedTotalShares,
 171 |     |                 "requestRedeem should never reduce SuperVault shares"
 172 |     |             );
 173 |     |         }
 174 |     |         return true;
 175 |     |     }
 176 |     | 
 177 |     |     /// @dev Property: `SuperVault::totalSupply` == SUM(user balances) + balanceOf(escrow)
 178 | *r  |     function invariant_shareSolvency() public returns (bool) {
 179 | *   |         uint256 sumOfShares = _sumTotalShares();
 180 | *   |         eq(superVault.totalSupply(), sumOfShares, "vault shares are insolvent");
 181 |     |         return true;
 182 |     |     }
 183 |     | 
 184 |     |     /// @dev Property: balanceOf(escrow) >= SUM(controllers.pendingRedeemRequest)
 185 | *r  |     function invariant_escrowBalance() public returns (bool) {
 186 | *   |         address[] memory actors = _getActors();
 187 |     | 
 188 | *   |         uint256 escrowBalance = superVault.balanceOf(address(superVaultEscrow));
 189 | *   |         uint256 pendingActorShares;
 190 | *   |         for (uint256 i; i < actors.length; i++) {
 191 | *   |             pendingActorShares += superVault.pendingRedeemRequest(0, actors[i]);
 192 |     |         }
 193 |     | 
 194 | *   |         gte(
 195 | *   |             escrowBalance,
 196 | *   |             pendingActorShares,
 197 |     |             "balanceOf(escrow) < SUM(controllers.pendingRedeemRequest)"
 198 |     |         );
 199 | *   |         return true;
 200 |     |     }
 201 |     | 
 202 |     |     /// @dev Property: maxMint should be 0 when aggregator is paused
 203 | *r  |     function invariant_maxMintZeroWhenPaused() public returns (bool) {
 204 | *   |         bool paused = superVaultAggregator.isStrategyPaused(
 205 | *   |             address(superVaultStrategy)
 206 |     |         );
 207 | *   |         uint256 maxMint = superVault.maxMint(_getActor());
 208 |     | 
 209 | *   |         if (paused) {
 210 | *   |             eq(maxMint, 0, "actor has nonzero maxMint when strategy is paused");
 211 |     |         }
 212 | *   |         return true;
 213 |     |     }
 214 |     | 
 215 |     |     /// @dev Property: maxDeposit should be 0 when strategy is paused
 216 | *r  |     function invariant_maxDepositZeroWhenPaused() public returns (bool) {
 217 | *   |         bool paused = superVaultAggregator.isStrategyPaused(
 218 | *   |             address(superVaultStrategy)
 219 |     |         );
 220 | *   |         uint256 maxDeposit = superVault.maxDeposit(_getActor());
 221 |     | 
 222 | *   |         if (paused) {
 223 | *   |             eq(
 224 | *   |                 maxDeposit,
 225 | *   |                 0,
 226 |     |                 "actor has nonzero maxDeposit when strategy is paused"
 227 |     |             );
 228 |     |         }
 229 |     |         return true;
 230 |     |     }
 231 |     | 
 232 |     |     /// @dev Property: SUM(accumulatorShares) doesn't change on SuperVault share transfers
 233 | *r  |     function invariant_accumulatorSharesSolvency() public returns (bool) {
 234 | *   |         if (_currentOp == OpType.TRANSFER) {
 235 | *   |             eq(
 236 | *   |                 _before.summedAccumulatorShares,
 237 | *   |                 _after.summedAccumulatorShares, // TODO: think about way to handle transfer on recipient
 238 |     |                 "SUM(accumulatorShares) changed on SuperVault share transfers"
 239 |     |             );
 240 |     |         }
 241 | *   |         return true;
 242 |     |     }
 243 |     | 
 244 |     |     /// @dev Property: SUM(accumulatorCostBasis) doesn't change on SuperVault share transfers
 245 | *r  |     function invariant_accumulatorCostBasisSolvency() public returns (bool) {
 246 | *   |         if (_currentOp == OpType.TRANSFER) {
 247 | *   |             eq(
 248 | *   |                 _before.summedAccumulatorCostBasis,
 249 | *   |                 _after.summedAccumulatorCostBasis,
 250 |     |                 "SUM(accumulatorCostBasis) changed on SuperVault share transfers"
 251 |     |             );
 252 |     |         }
 253 |     |         return true;
 254 |     |     }
 255 |     | 
 256 |     |     /// @dev Property: cancelRedeem should never alter the supply of SuperVault tokens
 257 | *r  |     function invariant_cancelDoesntChangeTotalSupply() public returns (bool) {
 258 | *   |         if (_currentOp == OpType.CANCEL) {
 259 | *   |             eq(
 260 | *   |                 _before.summedTotalShares,
 261 | *   |                 _after.summedTotalShares,
 262 |     |                 "cancelRedeem should never alter the supply of SuperVault tokens"
 263 |     |             );
 264 |     |         }
 265 |     |         return true;
 266 |     |     }
 267 |     | 
 268 |     |     /// @dev Property: if totalSupply > 0, then totalAssets > 0
 269 | *r  |     function invariant_assetBacking() public returns (bool) {
 270 | *   |         uint256 summedTotalAssets = _sumStrategyAssets();
 271 |     | 
 272 | *   |         if (superVault.totalSupply() > 0) {
 273 | *   |             gt(
 274 | *   |                 summedTotalAssets,
 275 | *   |                 0,
 276 |     |                 "if totalSupply > 0, then totalAssets > 0"
 277 |     |             );
 278 |     |         }
 279 | *   |         return true;
 280 |     |     }
 281 |     | 
 282 |     |     /// @dev Property: SUM(shares) * PPS == totalAssets
 283 | *r  |     function invariant_totalAssets() public returns (bool) {
 284 | *   |         uint256 totalShares = _sumTotalShares();
 285 | *   |         uint256 pps = superVaultAggregator.getPPS(address(superVaultStrategy));
 286 | *   |         uint256 implicitTotalAssets = (totalShares * pps) /
 287 | *   |             superVault.PRECISION();
 288 |     | 
 289 | *   |         uint256 vaultTotalAssets = superVault.totalAssets();
 290 | *   |         eq(
 291 | *   |             implicitTotalAssets,
 292 | *   |             vaultTotalAssets,
 293 |     |             "totalShares * pps != totalAssets"
 294 |     |         );
 295 |     |         return true;
 296 |     |     }
 297 |     | 
 298 |     |     /// @dev Property: When a user requests a redemption and the PPS is >= the user PPS, user averageRequestPPS must not decrease
 299 | *r  |     function invariant_avgPPSDoesntDecrease() public returns (bool) {
 300 | *   |         uint256 currentPrice = _before.oraclePPS;
 301 | *   |         uint256 beforeAvgPPS = _before.state[_getActor()].averageRequestPPS;
 302 | *   |         uint256 afterAvgPPS = _after.state[_getActor()].averageRequestPPS;
 303 |     | 
 304 | *   |         if (_currentOp == OpType.REQUEST && currentPrice >= beforeAvgPPS) {
 305 | *   |             gte(
 306 | *   |                 afterAvgPPS,
 307 | *   |                 beforeAvgPPS,
 308 |     |                 "when a user requests a redemption and the PPS is >= the user PPS, user averageRequestPPS must not decrease"
 309 |     |             );
 310 |     |         }
 311 |     |         return true;
 312 |     |     }
 313 |     | 
 314 |     |     /// @dev Property: previewMint and previewDeposit equivalence (from shares)
 315 | *r  |     function global_previewEquivalenceFromShares_ASSERTION_GLOBAL_PREVIEW_EQUIVALENCE_FROM_SHARES(uint256 shares) public {
 316 | *r  |         uint256 previewMintAssets = superVault.previewMint(shares);
 317 | *r  |         uint256 previewDepositShares = superVault.previewDeposit(
 318 |     |             previewMintAssets
 319 |     |         );
 320 | *   |         uint256 price = superVaultStrategy.getStoredPPS();
 321 |     | 
 322 | *   |         if (price > 0) {
 323 | *   |             eq(
 324 | *   |                 shares,
 325 | *   |                 previewDepositShares,
 326 | *   |                 ASSERTION_GLOBAL_PREVIEW_EQUIVALENCE_FROM_SHARES
 327 |     |             );
 328 |     |         }
 329 |     |     }
 330 |     | 
 331 |     |     /// @dev Property: previewMint and previewDeposit equivalence (from assets)
 332 | *r  |     function global_previewEquivalenceFromAssets_ASSERTION_GLOBAL_PREVIEW_EQUIVALENCE_FROM_ASSETS(uint256 assets) public {
 333 | *r  |         uint256 previewDepositShares = superVault.previewDeposit(assets);
 334 | *   |         uint256 previewMintAssets_under = superVault.previewMint(
 335 |     |             previewDepositShares
 336 |     |         );
 337 | *r  |         uint256 previewMintAssets_over = superVault.previewMint(
 338 | *   |             previewDepositShares + 1
 339 |     |         );
 340 | *   |         uint256 price = superVaultStrategy.getStoredPPS();
 341 |     | 
 342 | *   |         if (price > 0) {
 343 | *   |             gte(
 344 | *   |                 assets,
 345 | *   |                 previewMintAssets_under,
 346 | *   |                 ASSERTION_GLOBAL_PREVIEW_EQUIVALENCE_FROM_ASSETS
 347 |     |             );
 348 |     | 
 349 | *   |             lte(
 350 | *   |                 assets,
 351 | *   |                 previewMintAssets_over,
 352 | *   |                 ASSERTION_GLOBAL_PREVIEW_EQUIVALENCE_FROM_ASSETS
 353 |     |             );
 354 |     |         }
 355 |     |     }
 356 |     | 
 357 |     |     /// @dev Property: previewMint is >= convertToAssets
 358 | *r  |     function global_comparePreviewMintAndConvertToAssets_ASSERTION_GLOBAL_PREVIEW_MINT_GTE_CONVERT_TO_ASSETS(
 359 |     |         uint256 shares
 360 |     |     ) public {
 361 | *r  |         uint256 previewMintAssets = superVault.previewMint(shares);
 362 | *   |         uint256 convertToAssets = superVault.convertToAssets(shares);
 363 | *   |         gte(
 364 | *   |             previewMintAssets,
 365 | *   |             convertToAssets,
 366 | *   |             ASSERTION_GLOBAL_PREVIEW_MINT_GTE_CONVERT_TO_ASSETS
 367 |     |         );
 368 |     |     }
 369 |     | 
 370 |     |     /// @dev Property: convertToShares is >= previewDepositShares (equivalent without fees)
 371 | *r  |     function global_comparePreviewDepositAndConvertToShares_ASSERTION_GLOBAL_CONVERT_TO_SHARES_GTE_PREVIEW_DEPOSIT(
 372 |     |         uint256 assets
 373 |     |     ) public {
 374 | *r  |         uint256 previewDepositShares = superVault.previewDeposit(assets);
 375 | *r  |         uint256 convertToShares = superVault.convertToShares(assets);
 376 | *   |         gte(
 377 | *   |             convertToShares,
 378 | *   |             previewDepositShares,
 379 | *   |             ASSERTION_GLOBAL_CONVERT_TO_SHARES_GTE_PREVIEW_DEPOSIT
 380 |     |         );
 381 |     |     }
 382 |     | 
 383 |     |     // NOTE: Withdrawal properties are more nuanced, as we should ensure that no gain can be had and that losses are imputed to the controller receiving the assets
 384 |     | 
 385 |     |     /// @dev Property: After all redemptions are processed, the sum of all claimable is <= balance available
 386 | *r  |     function invariant_sumOfClaimable() public returns (bool) {
 387 | *   |         address[] memory actors = _getActors();
 388 |     | 
 389 | *   |         uint256 sumPending;
 390 | *   |         uint256 sumClaimable;
 391 | *   |         for (uint256 i; i < actors.length; i++) {
 392 | *   |             sumPending += superVault.pendingRedeemRequest(0, actors[i]);
 393 | *   |             sumClaimable += superVault.maxWithdraw(actors[i]);
 394 |     |         }
 395 |     | 
 396 | *   |         uint256 strategyBalance = MockERC20(superVault.asset()).balanceOf(
 397 | *   |             address(superVaultStrategy)
 398 |     |         );
 399 |     | 
 400 |     |         // precondition: all pending has been fulfilled
 401 | *   |         if (sumPending == 0) {
 402 | *   |             lte(
 403 | *   |                 sumClaimable,
 404 | *   |                 strategyBalance,
 405 |     |                 "sum of all claimable is > balance available"
 406 |     |             );
 407 |     |         }
 408 |     |         return true;
 409 |     |     }
 410 |     | 
 411 |     |     /// @dev Property: If the sum of assets in SuperVaultStrategy and yield strategies is 0, maxWithdraw should be 0
 412 | *r  |     function invariant_sumOfAssetsMaxWithdrawable() public returns (bool) {
 413 | *   |         uint256 summedTotalAssets = _sumStrategyAssets();
 414 |     | 
 415 | *   |         if (summedTotalAssets == 0) {
 416 | *   |             uint256 maxWithdraw = superVault.maxWithdraw(_getActor());
 417 | *   |             eq(
 418 | *   |                 maxWithdraw,
 419 | *   |                 0,
 420 |     |                 "if sum of assets in SuperVaultStrategy and yield strategies is 0, maxWithdraw should be 0"
 421 |     |             );
 422 |     |         }
 423 |     |         return true;
 424 |     |     }
 425 |     | 
 426 |     |     /// @dev Property: averageWithdrawPrice should never decrease when new redemptions are fulfilled at a higher PPS
 427 | *r  |     function invariant_avgPPSMonotonicity() public returns (bool) {
 428 | *   |         if (
 429 | *   |             _currentOp == OpType.FULFILL &&
 430 | *   |             _before.oraclePPS > _before.state[_getActor()].averageRequestPPS && // fulfilled at a higher price
 431 | *   |             _after.state[_getActor()].pendingRedeemRequest != 0 // redemptions have all been fulfilled/cancelled; avg gets reset to 0 in this case
 432 |     |         ) {
 433 |     |             gte(
 434 |     |                 _after.state[_getActor()].averageRequestPPS,
 435 |     |                 _before.state[_getActor()].averageRequestPPS,
 436 |     |                 "averageWithdrawPrice should not decrease when fulfilled at a higher PPS"
 437 |     |             );
 438 |     |         }
 439 |     |         return true;
 440 |     |     }
 441 |     | 
 442 |     |     /// @dev Property: state.accumulatorShares >= superVaultState[controllers[i]].pendingRedeemRequest for each user
 443 | *r  |     function invariant_accumulatorSharesGtPendingRequests() public returns (bool) {
 444 | *   |         address[] memory actors = _getActors();
 445 |     | 
 446 | *   |         for (uint256 i; i < actors.length; i++) {
 447 | *   |             ISuperVaultStrategy.SuperVaultState
 448 | *   |                 memory state = superVaultStrategy.getSuperVaultState(actors[i]);
 449 | *   |             gte(
 450 | *   |                 state.accumulatorShares,
 451 | *   |                 state.pendingRedeemRequest,
 452 |     |                 "state.accumulatorShares < state.pendingRedeemRequest"
 453 |     |             );
 454 |     |         }
 455 | *   |         return true;
 456 |     |     }
 457 |     | 
 458 |     |     /// @dev Property: accumulatorShares is always accurately increased
 459 | *r  |     function invariant_accumulatorSharesIncrease() public returns (bool) {
 460 | *   |         if (_currentOp == OpType.ADD) {
 461 | *   |             uint256 accumulatorSharesBefore = _before
 462 | *   |                 .state[_getActor()]
 463 |     |                 .accumulatorShares;
 464 | *   |             uint256 accumulatorSharesAfter = _after
 465 | *   |                 .state[_getActor()]
 466 |     |                 .accumulatorShares;
 467 | *   |             uint256 actorSharesBefore = _before.superVaultShares[_getActor()];
 468 | *   |             uint256 actorSharesAfter = _after.superVaultShares[_getActor()];
 469 | *   |             eq(
 470 | *   |                 accumulatorSharesAfter - accumulatorSharesBefore,
 471 | *   |                 actorSharesAfter - actorSharesBefore,
 472 |     |                 "accumulatorShares is always accurately updated"
 473 |     |             );
 474 |     |         }
 475 | *   |         return true;
 476 |     |     }
 477 |     | 
 478 |     |     /// @dev Property: accumulatorCostBasis is always accurately increased
 479 | *r  |     function invariant_accumulatorCostBasisIncrease() public returns (bool) {
 480 | *   |         if (_currentOp == OpType.ADD) {
 481 | *   |             uint256 accumulatorCostBasisBefore = _before
 482 | *   |                 .state[_getActor()]
 483 |     |                 .accumulatorCostBasis;
 484 | *   |             uint256 accumulatorCostBasisAfter = _after
 485 | *   |                 .state[_getActor()]
 486 |     |                 .accumulatorCostBasis;
 487 | *   |             eq(
 488 | *   |                 accumulatorCostBasisAfter - accumulatorCostBasisBefore,
 489 | *   |                 _after.strategyAssetBalance - _before.strategyAssetBalance,
 490 |     |                 "accumulatorShares is always accurately updated"
 491 |     |             );
 492 |     |         }
 493 |     |         return true;
 494 |     |     }
 495 |     | 
 496 |     |     /// @dev Property: redemptions only burn the requested amount of shares (within tolerance range)
 497 | *r  |     function invariant_fulfillOnlyBurnsRequestedAmount() public returns (bool) {
 498 | *   |         uint256 TOLERANCE_CONSTANT = 10 wei; // taken from SuperVaultStrategy
 499 |     | 
 500 | *   |         if (_currentOp == OpType.FULFILL) {
 501 | *   |             uint256 pendingRedeemDelta = _before.summedPendingRedeem -
 502 | *   |                 _after.summedPendingRedeem;
 503 | *   |             uint256 totalSupplyDelta = _before.summedTotalShares -
 504 | *   |                 _after.summedTotalShares;
 505 |     | 
 506 |     |             // Check that burned amount is within tolerance of requested amount
 507 | *   |             if (totalSupplyDelta < pendingRedeemDelta) {
 508 |     |                 // Burned less than requested - check within tolerance
 509 | *   |                 gte(
 510 | *   |                     totalSupplyDelta,
 511 | *   |                     pendingRedeemDelta - TOLERANCE_CONSTANT,
 512 |     |                     "burned less than requested beyond tolerance"
 513 |     |                 );
 514 |     |             } else {
 515 |     |                 // Burned more than requested - check within tolerance
 516 | *   |                 lte(
 517 |     |                     totalSupplyDelta,
 518 |     |                     pendingRedeemDelta + TOLERANCE_CONSTANT,
 519 |     |                     "burned more than requested beyond tolerance"
 520 |     |                 );
 521 |     |             }
 522 |     |         }
 523 | *   |         return true;
 524 |     |     }
 525 |     | 
 526 |     |     /// @dev Property: accumulatorShares decreases by the exact amounts requested when fulfilling redemptions
 527 | *r  |     function invariant_accumulatorSharesDecreaseOnFulfill_exact() public returns (bool) {
 528 | *   |         if (_currentOp == OpType.FULFILL) {
 529 | *   |             uint256 accumulatorSharesDelta = _before.summedAccumulatorShares -
 530 | *   |                 _after.summedAccumulatorShares;
 531 | *   |             uint256 totalSharesDelta = _before.summedTotalShares -
 532 | *   |                 _after.summedTotalShares;
 533 | *   |             eq(
 534 | *   |                 accumulatorSharesDelta,
 535 | *   |                 totalSharesDelta,
 536 |     |                 "accumulatorShares decreases by the exact amounts requested when fulfilling redemptions"
 537 |     |             );
 538 |     |         }
 539 | *   |         return true;
 540 |     |     }
 541 |     | 
 542 | *r  |     function invariant_accumulatorSharesDecreaseOnFulfill_with_tolerance()
 543 | *   |         public returns (bool)
 544 |     |     {
 545 | *   |         if (_currentOp == OpType.FULFILL) {
 546 | *   |             uint256 accumulatorSharesDelta = _before.summedAccumulatorShares -
 547 | *   |                 _after.summedAccumulatorShares;
 548 | *   |             uint256 totalSharesDelta = _before.summedTotalShares -
 549 | *   |                 _after.summedTotalShares;
 550 | *   |             if (accumulatorSharesDelta >= totalSharesDelta) {
 551 | *   |                 lte(
 552 | *   |                     accumulatorSharesDelta - totalSharesDelta,
 553 | *   |                     TOLERANCE,
 554 |     |                     "accumulatorShares decreases by more than TOLERANCE when fulfilling redemptions"
 555 |     |                 );
 556 |     |             } else {
 557 |     |                 lte(
 558 |     |                     totalSharesDelta - accumulatorSharesDelta,
 559 |     |                     TOLERANCE,
 560 |     |                     "accumulatorShares decreases by less than TOLERANCE when fulfilling redemptions"
 561 |     |                 );
 562 |     |             }
 563 |     |         }
 564 |     |         return true;
 565 |     |     }
 566 |     | 
 567 |     |     /// Optimization Setters
 568 |     | 
 569 | *r  |     function setpreviewAssetsGreater(uint256 shares) public {
 570 | *r  |         uint256 previewMintAssets = superVault.previewMint(shares);
 571 | *r  |         uint256 previewDepositAssets = superVault.previewDeposit(
 572 |     |             previewMintAssets
 573 |     |         );
 574 |     | 
 575 | *   |         if (previewMintAssets > previewDepositAssets) {
 576 | *   |             previewMintAssetsGreater = int256(previewMintAssets);
 577 |     |         } else {
 578 | *   |             previewDepositAssetsGreater = int256(previewDepositAssets);
 579 |     |         }
 580 |     |     }
 581 |     | 
 582 | *r  |     function setPreviewSharesGreater(uint256 assets) public {
 583 | *r  |         uint256 previewDepositShares = superVault.previewDeposit(assets);
 584 | *   |         uint256 previewMintShares = superVault.previewMint(
 585 |     |             previewDepositShares
 586 |     |         );
 587 |     | 
 588 | *   |         if (previewDepositShares > previewMintShares) {
 589 | *   |             previewDepositSharesGreater =
 590 | *   |                 int256(previewDepositShares) -
 591 | *   |                 int256(previewMintShares);
 592 |     |         } else {
 593 | *   |             previewMintSharesGreater =
 594 | *   |                 int256(previewMintShares) -
 595 | *   |                 int256(previewDepositShares);
 596 |     |         }
 597 |     |     }
 598 |     | 
 599 | *r  |     function setFulfilledDifference() public {
 600 | *   |         if (_currentOp == OpType.FULFILL) {
 601 | *   |             uint256 pendingRedeemDelta = _before.summedPendingRedeem -
 602 | *   |                 _after.summedPendingRedeem;
 603 | *   |             uint256 totalSupplyDelta = _before.summedTotalShares -
 604 | *   |                 _after.summedTotalShares;
 605 |     | 
 606 |     |             // Check that burned amount is within tolerance of requested amount
 607 | *   |             if (totalSupplyDelta < pendingRedeemDelta) {
 608 |     |                 // Burned less than requested
 609 | *   |                 int256 burnedLessThanRequested = int256(pendingRedeemDelta) -
 610 | *   |                     int256(totalSupplyDelta);
 611 |     |             } else {
 612 |     |                 // Burned more than requested
 613 |     |                 int256 burnedMoreThanRequested = int256(totalSupplyDelta) -
 614 |     |                     int256(pendingRedeemDelta);
 615 |     |             }
 616 |     |         }
 617 |     |     }
 618 |     | 
 619 |     |     /// Optimization Tests
 620 |     | 
 621 |     |     /// @dev Optimize the difference between the amount of assets in the system and claimable assets
 622 | *r  |     function optimize_maxDustAccumulation() public view returns (int256) {
 623 | *   |         address[] memory actors = _getActors();
 624 |     | 
 625 | *   |         uint256 summedClaimableRedemptionsAsAssets;
 626 | *   |         for (uint256 i; i < actors.length; i++) {
 627 | *   |             uint256 claimableRedemptions = superVault.claimableRedeemRequest(
 628 |     |                 0,
 629 | *   |                 actors[i]
 630 |     |             );
 631 | *   |             summedClaimableRedemptionsAsAssets += superVault.convertToAssets(
 632 |     |                 claimableRedemptions
 633 |     |             );
 634 |     |         }
 635 |     | 
 636 | *   |         uint256 totalAssets = _sumStrategyAssets();
 637 |     | 
 638 | *   |         return int256(totalAssets) - int256(summedClaimableRedemptionsAsAssets);
 639 |     |     }
 640 |     | 
 641 |     |     /// @dev Optimize the difference between the amount of claimable assets and assets in the system
 642 | *   |     function optimize_moreClaimableThanHeldDifference()
 643 |     |         public
 644 |     |         view
 645 | *   |         returns (int256)
 646 | *   |     {
 647 | *   |         address[] memory actors = _getActors();
 648 |     | 
 649 | *   |         uint256 summedClaimableRedemptionsAsAssets;
 650 | *   |         for (uint256 i; i < actors.length; i++) {
 651 | *   |             summedClaimableRedemptionsAsAssets += superVault.maxWithdraw(
 652 | *   |                 actors[i]
 653 |     |             );
 654 |     |         }
 655 |     | 
 656 | *   |         uint256 totalAssets = _sumStrategyAssets();
 657 |     | 
 658 | *   |         if (summedClaimableRedemptionsAsAssets > totalAssets) {
 659 | *   |             return
 660 | *   |                 int256(summedClaimableRedemptionsAsAssets) -
 661 |     |                 int256(totalAssets);
 662 |     |         }
 663 |     |     }
 664 |     | 
 665 | *r  |     function optimize_burnMoreThanRequestedInRedemption()
 666 |     |         public
 667 |     |         view
 668 |     |         returns (int256)
 669 |     |     {
 670 | *   |         return burnedMoreThanRequested;
 671 |     |     }
 672 |     | 
 673 | *   |     function optimize_burnLessThanRequestedInRedemption()
 674 |     |         public
 675 |     |         view
 676 |     |         returns (int256)
 677 |     |     {
 678 | *   |         return burnedLessThanRequested;
 679 |     |     }
 680 |     | 
 681 |     |     // function optimize_previewMintSharesGreater() public view returns (int256) {
 682 |     |     //     return previewMintSharesGreater;
 683 |     |     // }
 684 |     | 
 685 |     |     // function optimize_previewDepositSharesGreater()
 686 |     |     //     public
 687 |     |     //     view
 688 |     |     //     returns (int256)
 689 |     |     // {
 690 |     |     //     return previewDepositSharesGreater;
 691 |     |     // }
 692 |     | 
 693 |     |     // function optimize_previewMintAssetsGreater() public view returns (int256) {
 694 |     |     //     return previewMintAssetsGreater;
 695 |     |     // }
 696 |     | 
 697 |     |     // function optimize_previewDepositAssetsGreater()
 698 |     |     //     public
 699 |     |     //     view
 700 |     |     //     returns (int256)
 701 |     |     // {
 702 |     |     //     return previewDepositAssetsGreater;
 703 |     |     // }
 704 |     | 
 705 | *r  |     function optimize_assetBackingDifference() public view returns (int256) {
 706 | *   |         uint256 summedTotalAssets = _sumStrategyAssets();
 707 | *   |         uint256 totalSupply = superVault.totalSupply();
 708 |     | 
 709 | *   |         if (summedTotalAssets == 0 && totalSupply > 0) {
 710 |     |             return int256(totalSupply);
 711 |     |         }
 712 |     |     }
 713 |     | 
 714 |     |     // Canaries
 715 |     | 
 716 |     |     /// @dev Canary assertion helper. A failing input is expected to be discovered during fuzzing.
 717 | *r  |     function assert_canary_ASSERTION_CANARY(uint256 entropy) public {
 718 | *   |         t(entropy > 0, ASSERTION_CANARY);
 719 |     |     }
 720 |     | 
 721 |     |     /// @dev Canary global invariant expected to fail immediately.
 722 | *r  |     function invariant_canary() public returns (bool) {
 723 | *   |         t(false, INVARIANT_CANARY_GLOBAL_INVARIANT_FAILURE);
 724 |     |         return true;
 725 |     |     }
 726 |     | 
 727 |     |     // ERC7540 Properties from erc7540-reusable-properties
 728 |     | 
 729 |     |     /// @dev Property 7540-1: convertToAssets(totalSupply) == totalAssets unless price is 0.0
 730 | *r  |     function invariant_erc7540_1() public returns (bool) {
 731 | *   |         actor = _getActor();
 732 | *   |         t(
 733 | *   |             erc7540_1(address(superVault)),
 734 |     |             "ERC7540-1: convertToAssets(totalSupply) == totalAssets failed"
 735 |     |         );
 736 |     |         return true;
 737 |     |     }
 738 |     | 
 739 |     |     /// @dev Property 7540-2: convertToShares(totalAssets) == totalSupply unless price is 0.0
 740 | *r  |     function invariant_erc7540_2() public returns (bool) {
 741 | *   |         actor = _getActor();
 742 | *   |         t(
 743 | *   |             erc7540_2(address(superVault)),
 744 |     |             "ERC7540-2: convertToShares(totalAssets) == totalSupply failed"
 745 |     |         );
 746 |     |         return true;
 747 |     |     }
 748 |     | 
 749 |     |     /// @dev Property 7540-3: max* never reverts
 750 | *r  |     function invariant_erc7540_3() public returns (bool) {
 751 | *   |         actor = _getActor();
 752 | *   |         t(
 753 | *   |             erc7540_3(address(superVault)),
 754 |     |             "ERC7540-3: max* functions should never revert"
 755 |     |         );
 756 |     |         return true;
 757 |     |     }
 758 |     | 
 759 |     |     /// @dev Property 7540-4: claiming more than max always reverts
 760 | *r  |     function global_erc7540_4_deposit_ASSERTION_ERC7540_4_DEPOSIT(uint256 amt) public stateless {
 761 | *   |         actor = _getActor();
 762 | *   |         t(
 763 | *   |             erc7540_4_deposit(address(superVault), amt),
 764 | *   |             ASSERTION_ERC7540_4_DEPOSIT
 765 |     |         );
 766 |     |     }
 767 |     | 
 768 | *r  |     function global_erc7540_4_mint_ASSERTION_ERC7540_4_MINT(uint256 amt) public stateless {
 769 | *   |         actor = _getActor();
 770 | *   |         t(
 771 | *   |             erc7540_4_mint(address(superVault), amt),
 772 | *   |             ASSERTION_ERC7540_4_MINT
 773 |     |         );
 774 |     |     }
 775 |     | 
 776 | *r  |     function global_erc7540_4_withdraw_ASSERTION_ERC7540_4_WITHDRAW(uint256 amt) public stateless {
 777 | *   |         actor = _getActor();
 778 | *   |         t(
 779 | *   |             erc7540_4_withdraw(address(superVault), amt),
 780 | *   |             ASSERTION_ERC7540_4_WITHDRAW
 781 |     |         );
 782 |     |     }
 783 |     | 
 784 | *r  |     function global_erc7540_4_redeem_ASSERTION_ERC7540_4_REDEEM(uint256 amt) public stateless {
 785 | *   |         actor = _getActor();
 786 | *   |         t(
 787 | *   |             erc7540_4_redeem(address(superVault), amt),
 788 | *   |             ASSERTION_ERC7540_4_REDEEM
 789 |     |         );
 790 |     |     }
 791 |     | 
 792 |     |     /// @dev Property 7540-5: requestRedeem reverts if the share balance is less than amount
 793 | *r  |     function global_erc7540_5_ASSERTION_ERC7540_5(uint256 shares) public stateless {
 794 | *   |         actor = _getActor();
 795 | *   |         t(
 796 | *   |             erc7540_5(address(superVault), address(superVault), shares),
 797 | *   |             ASSERTION_ERC7540_5
 798 |     |         );
 799 |     |     }
 800 |     | 
 801 |     |     /// @dev Property 7540-6: preview* always reverts
 802 |     |     // NOTE: previewMint and previewDeposit don't revert because deposits are sync
 803 |     |     // function crytic_erc7540_6() public {
 804 |     |     //     actor = _getActor();
 805 |     |     //     t(
 806 |     |     //         erc7540_6(address(superVault)),
 807 |     |     //         "ERC7540-6: preview* functions should always revert"
 808 |     |     //     );
 809 |     |     // }
 810 |     | 
 811 |     |     /// @dev Property 7540-7: if max[method] > 0, then [method] (max) should not revert
 812 |     |     // NOTE: maxDeposit always returns type(uint256).max
 813 |     |     // function crytic_erc7540_7_deposit(uint256 amt) public {
 814 |     |     //     actor = _getActor();
 815 |     |     //     t(
 816 |     |     //         erc7540_7_deposit(address(superVault), amt),
 817 |     |     //         "ERC7540-7: deposit should not revert when amount <= max"
 818 |     |     //     );
 819 |     |     // }
 820 |     | 
 821 |     |     // NOTE: maxMint always returns type(uint256).max
 822 |     |     // function crytic_erc7540_7_mint(uint256 amt) public stateless {
 823 |     |     //     actor = _getActor();
 824 |     |     //     t(
 825 |     |     //         erc7540_7_mint(address(superVault), amt),
 826 |     |     //         "ERC7540-7: mint should not revert when amount <= max"
 827 |     |     //     );
 828 |     |     // }
 829 |     | 
 830 | *r  |     function global_erc7540_7_withdraw_ASSERTION_ERC7540_7_WITHDRAW(uint256 amt) public stateless {
 831 | *   |         actor = _getActor();
 832 | *   |         t(
 833 | *   |             erc7540_7_withdraw(address(superVault), amt),
 834 | *   |             ASSERTION_ERC7540_7_WITHDRAW
 835 |     |         );
 836 |     |     }
 837 |     | 
 838 |     |     // NOTE: this implements the check from ERC7540Properties directly because SuperVault logic implementation allows amt to be nonzero but round down to 0 when assets passed into redeem are calculated
 839 | *r  |     function global_erc7540_7_redeem_ASSERTION_ERC7540_7_REDEEM(uint256 amt) public stateless {
 840 | *   |         actor = _getActor();
 841 |     | 
 842 | *   |         uint256 maxRedeem = superVault.maxRedeem(actor);
 843 | *   |         amt = between(amt, 0, maxRedeem);
 844 |     | 
 845 | *   |         if (amt == 0) {
 846 | *   |             return; // Skip
 847 |     |         }
 848 |     | 
 849 | *   |         uint256 averageWithdrawPrice = superVaultStrategy
 850 | *   |             .getAverageWithdrawPrice(actor);
 851 |     | 
 852 |     |         // calculates assets in the same way as redeem to confirm that a nonzero amount is being requested
 853 | *   |         uint256 assets = amt.mulDiv(
 854 | *   |             averageWithdrawPrice,
 855 | *   |             superVault.PRECISION(),
 856 | *   |             Math.Rounding.Floor
 857 |     |         );
 858 |     | 
 859 | *   |         try superVault.redeem(amt, actor, actor) {} catch {
 860 |     |             if (amt > 0 && assets > 0) {
 861 |     |                 t(
 862 |     |                     false,
 863 |     |                     ASSERTION_ERC7540_7_REDEEM
 864 |     |                 );
 865 |     |             }
 866 |     |         }
 867 |     |     }
 868 |     | }
 869 |     | 

/opt/scfuzzbench/work/target/test/recon/Setup.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | // External dependencies
   5 |     | import {BaseSetup} from "@chimera/BaseSetup.sol";
   6 |     | import {vm} from "@chimera/Hevm.sol";
   7 |     | import {ActorManager} from "@recon/ActorManager.sol";
   8 |     | import {AssetManager} from "@recon/AssetManager.sol";
   9 |     | import {Utils} from "@recon/Utils.sol";
  10 |     | // ERC4626 Hooks
  11 |     | import {Deposit4626VaultHook} from "lib/v2-core/src/hooks/vaults/4626/Deposit4626VaultHook.sol";
  12 |     | import {ApproveAndDeposit4626VaultHook} from "lib/v2-core/src/hooks/vaults/4626/ApproveAndDeposit4626VaultHook.sol";
  13 |     | import {Redeem4626VaultHook} from "lib/v2-core/src/hooks/vaults/4626/Redeem4626VaultHook.sol";
  14 |     | 
  15 |     | // ERC5115 Hooks
  16 |     | import {Deposit5115VaultHook} from "lib/v2-core/src/hooks/vaults/5115/Deposit5115VaultHook.sol";
  17 |     | import {ApproveAndDeposit5115VaultHook} from "lib/v2-core/src/hooks/vaults/5115/ApproveAndDeposit5115VaultHook.sol";
  18 |     | import {Redeem5115VaultHook} from "lib/v2-core/src/hooks/vaults/5115/Redeem5115VaultHook.sol";
  19 |     | 
  20 |     | // ERC7540 Hooks
  21 |     | import {Deposit7540VaultHook} from "lib/v2-core/src/hooks/vaults/7540/Deposit7540VaultHook.sol";
  22 |     | import {Redeem7540VaultHook} from "lib/v2-core/src/hooks/vaults/7540/Redeem7540VaultHook.sol";
  23 |     | import {RequestDeposit7540VaultHook} from "lib/v2-core/src/hooks/vaults/7540/RequestDeposit7540VaultHook.sol";
  24 |     | import {RequestRedeem7540VaultHook} from "lib/v2-core/src/hooks/vaults/7540/RequestRedeem7540VaultHook.sol";
  25 |     | import {ApproveAndRequestDeposit7540VaultHook} from "lib/v2-core/src/hooks/vaults/7540/ApproveAndRequestDeposit7540VaultHook.sol";
  26 |     | import {CancelDepositRequest7540Hook} from "lib/v2-core/src/hooks/vaults/7540/CancelDepositRequest7540Hook.sol";
  27 |     | import {CancelRedeemRequest7540Hook} from "lib/v2-core/src/hooks/vaults/7540/CancelRedeemRequest7540Hook.sol";
  28 |     | import {ClaimCancelDepositRequest7540Hook} from "lib/v2-core/src/hooks/vaults/7540/ClaimCancelDepositRequest7540Hook.sol";
  29 |     | import {ClaimCancelRedeemRequest7540Hook} from "lib/v2-core/src/hooks/vaults/7540/ClaimCancelRedeemRequest7540Hook.sol";
  30 |     | import {Withdraw7540VaultHook} from "lib/v2-core/src/hooks/vaults/7540/Withdraw7540VaultHook.sol";
  31 |     | 
  32 |     | // Super Vault Hooks
  33 |     | import {CancelRedeemHook} from "lib/v2-core/src/hooks/vaults/super-vault/CancelRedeemHook.sol";
  34 |     | import {Withdraw7540VaultHook as SuperVaultWithdraw7540VaultHook} from "lib/v2-core/src/hooks/vaults/super-vault/Withdraw7540VaultHook.sol";
  35 |     | 
  36 |     | // Source dependencies
  37 |     | import "src/SuperVault/SuperVault.sol";
  38 |     | import "src/SuperVault/SuperVaultAggregator.sol";
  39 |     | import "src/SuperVault/SuperVaultEscrow.sol";
  40 |     | import "src/SuperVault/SuperVaultStrategy.sol";
  41 |     | import "src/SuperGovernor.sol";
  42 |     | import {ISuperVaultAggregator} from "src/interfaces/SuperVault/ISuperVaultAggregator.sol";
  43 |     | import {ISuperVaultStrategy} from "src/interfaces/SuperVault/ISuperVaultStrategy.sol";
  44 |     | import {MockYieldSourceOracle} from "test/mocks/MockYieldSourceOracle.sol";
  45 |     | 
  46 |     | // Test suite dependencies
  47 |     | import {YieldManager, YieldSourceType} from "test/recon/managers/YieldManager.sol";
  48 |     | import {MerkleTestHelper} from "test/recon/helpers/MerkleTestHelper.sol";
  49 |     | import {UnsafeSuperVaultAggregator} from "test/recon/helpers/UnsafeSuperVaultAggregator.sol";
  50 |     | import {MockERC4626YieldSourceOracle} from "test/recon/mocks/MockERC4626YieldSourceOracle.sol";
  51 |     | import {MockERC5115YieldSourceOracle} from "test/recon/mocks/MockERC5115YieldSourceOracle.sol";
  52 |     | import {MockERC7540YieldSourceOracle} from "test/recon/mocks/MockERC7540YieldSourceOracle.sol";
  53 |     | import {MockECDSAPPSOracle} from "test/recon/mocks/MockECDSAPPSOracle.sol";
  54 |     | 
  55 |     | abstract contract Setup is
  56 |     |     BaseSetup,
  57 |     |     ActorManager,
  58 |     |     AssetManager,
  59 |     |     YieldManager,
  60 |     |     Utils
  61 |     | {
  62 |     |     // Configuration constants
  63 | *   |     uint8 internal constant DECIMALS = 18;
  64 |     |     address asset;
  65 | *   |     address feeRecipient = address(0xbeef);
  66 |     | 
  67 |     |     // Core contracts
  68 |     |     SuperGovernor superGovernor;
  69 |     |     SuperVault superVault;
  70 |     |     UnsafeSuperVaultAggregator superVaultAggregator;
  71 |     |     SuperVaultEscrow superVaultEscrow;
  72 |     |     SuperVaultStrategy superVaultStrategy;
  73 |     | 
  74 |     |     // Implementation contracts for aggregator
  75 |     |     SuperVault vaultImpl;
  76 |     |     SuperVaultStrategy strategyImpl;
  77 |     |     SuperVaultEscrow escrowImpl;
  78 |     | 
  79 |     |     // Helpers
  80 |     |     MerkleTestHelper merkleHelper;
  81 |     | 
  82 |     |     // ERC4626 Hooks
  83 |     |     ApproveAndDeposit4626VaultHook approveAndDeposit4626Hook;
  84 |     |     Deposit4626VaultHook deposit4626Hook;
  85 |     |     Redeem4626VaultHook redeem4626Hook;
  86 |     | 
  87 |     |     // ERC5115 Hooks
  88 |     |     ApproveAndDeposit5115VaultHook approveAndDeposit5115Hook;
  89 |     |     Deposit5115VaultHook deposit5115Hook;
  90 |     |     Redeem5115VaultHook redeem5115Hook;
  91 |     | 
  92 |     |     // ERC7540 Hooks
  93 |     |     Deposit7540VaultHook deposit7540Hook;
  94 |     |     Redeem7540VaultHook redeem7540Hook;
  95 |     |     RequestDeposit7540VaultHook requestDeposit7540Hook;
  96 |     |     RequestRedeem7540VaultHook requestRedeem7540Hook;
  97 |     |     ApproveAndRequestDeposit7540VaultHook approveAndRequestDeposit7540Hook;
  98 |     |     CancelDepositRequest7540Hook cancelDepositRequest7540Hook;
  99 |     |     CancelRedeemRequest7540Hook cancelRedeemRequest7540Hook;
 100 |     |     ClaimCancelDepositRequest7540Hook claimCancelDepositRequest7540Hook;
 101 |     |     ClaimCancelRedeemRequest7540Hook claimCancelRedeemRequest7540Hook;
 102 |     |     Withdraw7540VaultHook withdraw7540Hook;
 103 |     | 
 104 |     |     // Super Vault Hooks
 105 |     |     CancelRedeemHook cancelRedeemHook;
 106 |     |     SuperVaultWithdraw7540VaultHook superVaultWithdraw7540Hook;
 107 |     | 
 108 |     |     // Mocks
 109 |     |     MockERC4626YieldSourceOracle erc4626YieldSourceOracle;
 110 |     |     MockERC5115YieldSourceOracle erc5115YieldSourceOracle;
 111 |     |     MockERC7540YieldSourceOracle erc7540YieldSourceOracle;
 112 |     |     MockECDSAPPSOracle ECDSAPPSOracle;
 113 |     | 
 114 |     |     // Yield sources for different standards
 115 |     |     address erc4626YieldSource;
 116 |     |     address erc5115YieldSource;
 117 |     |     address erc7540YieldSource;
 118 |     | 
 119 |     |     // Ghosts
 120 |     |     bool hasUpdatedPPS;
 121 |     |     int256 burnedMoreThanRequested;
 122 |     |     int256 burnedLessThanRequested;
 123 |     |     int256 previewMintSharesGreater; // setPreviewSharesGreater
 124 |     |     int256 previewDepositSharesGreater; // setPreviewSharesGreater
 125 |     |     int256 previewMintAssetsGreater; // setpreviewAssetsGreater
 126 |     |     int256 previewDepositAssetsGreater; // setpreviewAssetsGreater
 127 |     | 
 128 |     |     // Canaries
 129 |     |     bool executeHooksClampedSuccess;
 130 |     |     bool executeHooksSuccess;
 131 |     |     bool fulfillRedeemRequestsSuccess;
 132 |     |     bool hasDeployedNewVault;
 133 |     | 
 134 |     |     /// === MODIFIERS === ///
 135 |     |     /// Prank admin and actor
 136 |     | 
 137 |     |     modifier asAdmin() {
 138 | *   |         vm.prank(address(this));
 139 |     |         _;
 140 |     |     }
 141 |     | 
 142 |     |     modifier asActor() {
 143 | *   |         vm.prank(address(_getActor()));
 144 |     |         _;
 145 |     |     }
 146 |     | 
 147 |     |     /// Makes a handler have no side effects
 148 |     |     /// The fuzzer will call this anyway, and because it reverts it will be removed from shrinking
 149 |     |     /// Replace the "withGhosts" with "stateless" to make the code clean
 150 |     |     ///
 151 |     |     /// Under Foundry with `assertions_revert = false` a failing t()/vm.assert* only records a
 152 |     |     /// journaled write to the global fail slot, which the trailing revert would erase — making
 153 |     |     /// every stateless assertion property invisible to the Foundry leg. Re-raise a failure
 154 |     |     /// recorded during this call as Panic(0x01), which Foundry classifies as an assertion
 155 |     |     /// failure; under echidna/medusa/recon a failing t() already reverted with Panic before
 156 |     |     /// reaching this point, so the extra check never fires there.
 157 |     |     modifier stateless() {
 158 | *   |         bool preFailed = _foundryFailSlotSet();
 159 |     |         _;
 160 | *   |         if (!preFailed && _foundryFailSlotSet()) assert(false);
 161 | *r  |         revert("stateless");
 162 |     |     }
 163 |     | 
 164 |     |     // bytes32("failed") — Foundry's GLOBAL_FAIL_SLOT on the cheatcode address, written
 165 |     |     // (journaled sstore of 1) by non-reverting vm.assert* failures.
 166 |     |     bytes32 internal constant _FOUNDRY_FAIL_SLOT =
 167 |     |         0x6661696c65640000000000000000000000000000000000000000000000000000;
 168 |     | 
 169 |     |     /// Probes the Foundry fail slot with a raw staticcall so fuzzers without the `load`
 170 |     |     /// cheatcode simply report "not set" instead of reverting.
 171 | *   |     function _foundryFailSlotSet() internal view returns (bool) {
 172 | *   |         (bool ok, bytes memory ret) = address(vm).staticcall(
 173 | *   |             abi.encodeWithSignature("load(address,bytes32)", address(vm), _FOUNDRY_FAIL_SLOT)
 174 |     |         );
 175 | *   |         return ok && ret.length >= 32 && abi.decode(ret, (bytes32)) != bytes32(0);
 176 |     |     }
 177 |     | 
 178 |     |     /// === Setup === ///
 179 |     |     /// This contains all calls to be performed in the tester constructor, both for Echidna and Foundry
 180 | *   |     function setup() internal virtual override {
 181 |     |         // 1. Add additional actors
 182 | *   |         _addActor(address(0x100)); // Actor 1
 183 | *   |         _addActor(address(0x200)); // Actor 2
 184 |     | 
 185 |     |         // 2. Create assets using AssetManager
 186 | *   |         _newAsset(DECIMALS); // Deploy token with 18 decimals
 187 | *   |         _newAsset(DECIMALS); // UP token
 188 |     | 
 189 | *   |         _switchAsset(0);
 190 |     | 
 191 |     |         // 3. Deploy all three types of yield sources using YieldManager
 192 |     |         // Deploy ERC4626 yield source (default)
 193 | *   |         erc4626YieldSource = _newYieldSource(
 194 | *   |             _getAsset(),
 195 | *   |             YieldSourceType.ERC4626
 196 |     |         );
 197 |     | 
 198 |     |         // Deploy ERC5115 yield source
 199 | *   |         erc5115YieldSource = _newYieldSource(
 200 | *   |             _getAsset(),
 201 | *   |             YieldSourceType.ERC5115
 202 |     |         );
 203 |     | 
 204 |     |         // Deploy ERC7540 yield source
 205 | *   |         erc7540YieldSource = _newYieldSource(
 206 | *   |             _getAsset(),
 207 | *   |             YieldSourceType.ERC7540
 208 |     |         );
 209 |     | 
 210 |     |         // Set ERC4626 as the default active yield source
 211 | *   |         _switchYieldSource(0); // Switch to first yield source in the array (ERC4626)
 212 |     | 
 213 |     |         // 4. Deploy SuperGovernor first (required by other contracts)
 214 | *   |         superGovernor = new SuperGovernor(
 215 | *   |             address(this), // superGovernor role
 216 | *   |             address(this), // governor role
 217 | *   |             address(this), // bankManager role
 218 | *   |             address(this), // gasManager role
 219 | *   |             feeRecipient, // treasury
 220 | *   |             address(this) // prover
 221 |     |         );
 222 |     | 
 223 |     |         // 5. Deploy implementation contracts for the aggregator
 224 | *   |         vaultImpl = new SuperVault(address(superGovernor));
 225 | *   |         strategyImpl = new SuperVaultStrategy(address(superGovernor));
 226 | *   |         escrowImpl = new SuperVaultEscrow();
 227 |     | 
 228 |     |         // 6. Deploy SuperVaultAggregator with implementation contracts
 229 | *   |         superVaultAggregator = new UnsafeSuperVaultAggregator(
 230 | *   |             address(superGovernor),
 231 | *   |             address(vaultImpl),
 232 | *   |             address(strategyImpl),
 233 |     |             address(escrowImpl)
 234 |     |         );
 235 |     | 
 236 |     |         // 7. Register the SuperVaultAggregator and UpToken address with SuperGovernor
 237 | *   |         superGovernor.setAddress(
 238 | *   |             superGovernor.SUPER_VAULT_AGGREGATOR(),
 239 | *   |             address(superVaultAggregator)
 240 |     |         );
 241 |     | 
 242 | *   |         address[] memory assets = _getAssets();
 243 | *   |         superGovernor.setAddress(superGovernor.UP(), assets[1]); // the second deployed token in the AssetManager is the UPToken
 244 | *   |         superGovernor.setAddress(superGovernor.SUPER_BANK(), address(this));
 245 |     | 
 246 |     |         // 8. Deploy Mocks and Oracles
 247 |     | 
 248 |     |         // Deploy specific oracles for each yield source type
 249 | *   |         erc4626YieldSourceOracle = new MockERC4626YieldSourceOracle();
 250 | *   |         erc5115YieldSourceOracle = new MockERC5115YieldSourceOracle();
 251 | *   |         erc7540YieldSourceOracle = new MockERC7540YieldSourceOracle();
 252 | *   |         ECDSAPPSOracle = new MockECDSAPPSOracle();
 253 |     | 
 254 |     |         // ECDSAPPSOracle setup
 255 | *   |         superGovernor.setActivePPSOracle(address(ECDSAPPSOracle));
 256 | *   |         ECDSAPPSOracle.setSUPER_GOVERNORReturn(address(superVaultAggregator));
 257 |     | 
 258 |     |         // Set valid assets for all oracles
 259 | *   |         asset = _getAsset();
 260 | *   |         erc4626YieldSourceOracle.setValidAsset(asset, true);
 261 | *   |         erc5115YieldSourceOracle.setValidAsset(asset, true);
 262 | *   |         erc7540YieldSourceOracle.setValidAsset(asset, true);
 263 |     | 
 264 |     |         // 9. Create a vault trio using the aggregator
 265 | *   |         ISuperVaultAggregator.VaultCreationParams
 266 | *   |             memory params = ISuperVaultAggregator.VaultCreationParams({
 267 | *   |                 asset: _getAsset(), // Use the token created by AssetManager
 268 |     |                 name: "SuperVault",
 269 |     |                 symbol: "SV",
 270 | *   |                 mainManager: address(this), // CONFIGURABLE: This parameter can be modified via target functions
 271 | *   |                 secondaryManagers: new address[](0), // CONFIGURABLE: This parameter can be modified via target functions
 272 | *   |                 minUpdateInterval: 5, // CONFIGURABLE: This parameter can be modified via target functions
 273 | *   |                 maxStaleness: 300, // CONFIGURABLE: This parameter can be modified via target functions
 274 | *   |                 feeConfig: ISuperVaultStrategy.FeeConfig({
 275 | *   |                     performanceFeeBps: 1000, // 10% performance fee
 276 | *   |                     managementFeeBps: 100, // 1% management fee
 277 | *   |                     recipient: feeRecipient
 278 |     |                 })
 279 |     |             });
 280 |     | 
 281 | *   |         (
 282 |     |             address vaultAddr,
 283 |     |             address strategyAddr,
 284 |     |             address escrowAddr
 285 | *   |         ) = superVaultAggregator.createVault(params);
 286 |     | 
 287 |     |         // 10. Store the deployed contracts
 288 | *   |         superVault = SuperVault(vaultAddr);
 289 | *   |         superVaultStrategy = SuperVaultStrategy(payable(strategyAddr));
 290 | *   |         superVaultEscrow = SuperVaultEscrow(escrowAddr);
 291 |     | 
 292 |     |         /// 11. Deploy all hook contracts and helper
 293 | *   |         merkleHelper = new MerkleTestHelper();
 294 |     | 
 295 |     |         // Deploy ERC4626 Hooks
 296 | *   |         approveAndDeposit4626Hook = new ApproveAndDeposit4626VaultHook();
 297 | *   |         deposit4626Hook = new Deposit4626VaultHook();
 298 | *   |         redeem4626Hook = new Redeem4626VaultHook();
 299 |     | 
 300 |     |         // Deploy ERC5115 Hooks
 301 | *   |         approveAndDeposit5115Hook = new ApproveAndDeposit5115VaultHook();
 302 | *   |         deposit5115Hook = new Deposit5115VaultHook();
 303 | *   |         redeem5115Hook = new Redeem5115VaultHook();
 304 |     | 
 305 |     |         // Deploy ERC7540 Hooks
 306 | *   |         deposit7540Hook = new Deposit7540VaultHook();
 307 | *   |         redeem7540Hook = new Redeem7540VaultHook();
 308 | *   |         requestDeposit7540Hook = new RequestDeposit7540VaultHook();
 309 | *   |         requestRedeem7540Hook = new RequestRedeem7540VaultHook();
 310 | *   |         approveAndRequestDeposit7540Hook = new ApproveAndRequestDeposit7540VaultHook();
 311 | *   |         cancelDepositRequest7540Hook = new CancelDepositRequest7540Hook();
 312 | *   |         cancelRedeemRequest7540Hook = new CancelRedeemRequest7540Hook();
 313 | *   |         claimCancelDepositRequest7540Hook = new ClaimCancelDepositRequest7540Hook();
 314 | *   |         claimCancelRedeemRequest7540Hook = new ClaimCancelRedeemRequest7540Hook();
 315 | *   |         withdraw7540Hook = new Withdraw7540VaultHook();
 316 |     | 
 317 |     |         // Deploy Super Vault Hooks
 318 | *   |         cancelRedeemHook = new CancelRedeemHook();
 319 | *   |         superVaultWithdraw7540Hook = new SuperVaultWithdraw7540VaultHook();
 320 |     | 
 321 |     |         // Register all hooks with SuperGovernor
 322 |     |         // ERC4626 Hooks (deposit hooks are regular hooks, redeem hooks are fulfill request hooks)
 323 | *   |         superGovernor.registerHook(address(approveAndDeposit4626Hook), false);
 324 | *   |         superGovernor.registerHook(address(deposit4626Hook), false);
 325 | *   |         superGovernor.registerHook(address(redeem4626Hook), true); // fulfill request hook
 326 |     | 
 327 |     |         // ERC5115 Hooks
 328 | *   |         superGovernor.registerHook(address(approveAndDeposit5115Hook), false);
 329 | *   |         superGovernor.registerHook(address(deposit5115Hook), false);
 330 | *   |         superGovernor.registerHook(address(redeem5115Hook), true); // fulfill request hook
 331 |     | 
 332 |     |         // ERC7540 Hooks (deposit/request hooks are regular hooks, redeem/withdraw hooks are fulfill request hooks)
 333 | *   |         superGovernor.registerHook(address(deposit7540Hook), false);
 334 | *   |         superGovernor.registerHook(address(redeem7540Hook), true); // fulfill request hook
 335 | *   |         superGovernor.registerHook(address(requestDeposit7540Hook), false);
 336 | *   |         superGovernor.registerHook(address(requestRedeem7540Hook), false);
 337 | *   |         superGovernor.registerHook(
 338 | *   |             address(approveAndRequestDeposit7540Hook),
 339 |     |             false
 340 |     |         );
 341 | *   |         superGovernor.registerHook(
 342 | *   |             address(cancelDepositRequest7540Hook),
 343 |     |             false
 344 |     |         );
 345 | *   |         superGovernor.registerHook(address(cancelRedeemRequest7540Hook), false);
 346 | *   |         superGovernor.registerHook(
 347 | *   |             address(claimCancelDepositRequest7540Hook),
 348 |     |             false
 349 |     |         );
 350 | *   |         superGovernor.registerHook(
 351 | *   |             address(claimCancelRedeemRequest7540Hook),
 352 |     |             false
 353 |     |         );
 354 | *   |         superGovernor.registerHook(address(withdraw7540Hook), true); // fulfill request hook
 355 |     | 
 356 |     |         // Super Vault Hooks
 357 | *   |         superGovernor.registerHook(address(cancelRedeemHook), false);
 358 | *   |         superGovernor.registerHook(address(superVaultWithdraw7540Hook), true); // fulfill request hook
 359 |     | 
 360 |     |         // 12. Set up approval array for contracts that need token access
 361 | *   |         address[] memory approvalArray = new address[](6);
 362 | *   |         approvalArray[0] = address(superVault);
 363 | *   |         approvalArray[1] = address(superVaultStrategy);
 364 | *   |         approvalArray[2] = address(superVaultAggregator);
 365 | *   |         approvalArray[3] = erc4626YieldSource;
 366 | *   |         approvalArray[4] = erc5115YieldSource;
 367 | *   |         approvalArray[5] = erc7540YieldSource;
 368 |     | 
 369 |     |         // 13. Finalize asset deployment (mints to actors and sets approvals)
 370 | *   |         _finalizeAssetDeployment(_getActors(), approvalArray, type(uint88).max);
 371 |     |     }
 372 |     | 
 373 |     |     /// Get hook addresses for different yield source types
 374 |     | 
 375 | *   |     function _getApproveAndDepositHookForType(
 376 |     |         YieldSourceType sourceType
 377 | *   |     ) internal view returns (address) {
 378 | *   |         if (sourceType == YieldSourceType.ERC4626) {
 379 | *   |             return address(approveAndDeposit4626Hook);
 380 | *   |         } else if (sourceType == YieldSourceType.ERC5115) {
 381 | *   |             return address(approveAndDeposit5115Hook);
 382 | *   |         } else if (sourceType == YieldSourceType.ERC7540) {
 383 | *   |             return address(approveAndRequestDeposit7540Hook);
 384 |     |         }
 385 |     |         return address(0);
 386 |     |     }
 387 |     | 
 388 | *   |     function _getRedeemHookForType(
 389 |     |         YieldSourceType sourceType
 390 | *   |     ) internal view returns (address) {
 391 | *   |         if (sourceType == YieldSourceType.ERC4626) {
 392 | *   |             return address(redeem4626Hook);
 393 | *   |         } else if (sourceType == YieldSourceType.ERC5115) {
 394 | *   |             return address(redeem5115Hook);
 395 | *   |         } else if (sourceType == YieldSourceType.ERC7540) {
 396 | *   |             return address(redeem7540Hook);
 397 |     |         }
 398 |     |         return address(0);
 399 |     |     }
 400 |     | 
 401 |     |     /// Get oracle addresses for different yield source types
 402 |     | 
 403 | *   |     function _getYieldSourceOracleForType(
 404 |     |         YieldSourceType sourceType
 405 | *   |     ) internal view returns (address) {
 406 | *   |         if (sourceType == YieldSourceType.ERC4626) {
 407 | *   |             return address(erc4626YieldSourceOracle);
 408 | *   |         } else if (sourceType == YieldSourceType.ERC5115) {
 409 | *   |             return address(erc5115YieldSourceOracle);
 410 | *   |         } else if (sourceType == YieldSourceType.ERC7540) {
 411 | *   |             return address(erc7540YieldSourceOracle);
 412 |     |         }
 413 |     |     }
 414 |     | 
 415 |     |     /// @dev Helper function to determine yield source type from address
 416 | *   |     function _getYieldSourceTypeFromAddress(
 417 |     |         address yieldSource
 418 | *   |     ) internal view returns (YieldSourceType) {
 419 |     |         // Get all available yield sources from YieldManager
 420 | *   |         address[] memory yieldSources = _getYieldSources();
 421 |     | 
 422 |     |         // Check which index matches the current yield source
 423 | *   |         for (uint256 i = 0; i < yieldSources.length; i++) {
 424 | *   |             if (yieldSources[i] == yieldSource) {
 425 |     |                 // Return the corresponding type based on creation order:
 426 |     |                 // Index 0: ERC4626, Index 1: ERC5115, Index 2: ERC7540
 427 | *   |                 if (i == 0) return YieldSourceType.ERC4626;
 428 | *   |                 if (i == 1) return YieldSourceType.ERC5115;
 429 | *   |                 if (i == 2) return YieldSourceType.ERC7540;
 430 |     |             }
 431 |     |         }
 432 |     | 
 433 |     |         // Default to ERC4626 if not found
 434 | *   |         return YieldSourceType.ERC4626;
 435 |     |     }
 436 |     | 
 437 |     |     function _getERC4626YieldSourceOracle() internal view returns (address) {
 438 |     |         return address(erc4626YieldSourceOracle);
 439 |     |     }
 440 |     | 
 441 |     |     function _getERC5115YieldSourceOracle() internal view returns (address) {
 442 |     |         return address(erc5115YieldSourceOracle);
 443 |     |     }
 444 |     | 
 445 |     |     function _getERC7540YieldSourceOracle() internal view returns (address) {
 446 |     |         return address(erc7540YieldSourceOracle);
 447 |     |     }
 448 |     | 
 449 |     |     // Helpers
 450 | *r  |     function _getRandomActor(uint256 entropy) public view returns (address) {
 451 | *   |         address[] memory actors = _getActors();
 452 |     | 
 453 | *   |         return actors[entropy % actors.length];
 454 |     |     }
 455 |     | }
 456 |     | 

/opt/scfuzzbench/work/target/test/recon/TargetFunctions.sol
  1 |     | // SPDX-License-Identifier: GPL-2.0
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | // Chimera deps
  5 |     | import {vm} from "@chimera/Hevm.sol";
  6 |     | 
  7 |     | // Helpers
  8 |     | import {Panic} from "@recon/Panic.sol";
  9 |     | 
 10 |     | // Targets
 11 |     | // NOTE: Always import and apply them in alphabetical order, so much easier to debug!
 12 |     | import {AdminTargets} from "./targets/AdminTargets.sol";
 13 |     | import {DoomsdayTargets} from "./targets/DoomsdayTargets.sol";
 14 |     | import {ManagersTargets} from "./targets/ManagersTargets.sol";
 15 |     | import {OracleTargets} from "./targets/OracleTargets.sol";
 16 |     | import {SuperVaultTargets} from "./targets/SuperVaultTargets.sol";
 17 |     | import {SuperVaultAggregatorTargets} from "./targets/SuperVaultAggregatorTargets.sol";
 18 |     | import {SuperVaultEscrowTargets} from "./targets/SuperVaultEscrowTargets.sol";
 19 |     | import {SuperVaultStrategyTargets} from "./targets/SuperVaultStrategyTargets.sol";
 20 |     | import {SuperGovernorTargets} from "./targets/SuperGovernorTargets.sol";
 21 |     | import {YieldSourceTargets} from "./targets/YieldSourceTargets.sol";
 22 |     | 
 23 |     | abstract contract TargetFunctions is
 24 |     |     AdminTargets,
 25 |     |     DoomsdayTargets,
 26 |     |     ManagersTargets,
 27 |     |     OracleTargets,
 28 |     |     SuperVaultTargets,
 29 |     |     SuperVaultAggregatorTargets,
 30 |     |     SuperVaultEscrowTargets,
 31 |     |     SuperVaultStrategyTargets,
 32 |     |     SuperGovernorTargets,
 33 |     |     YieldSourceTargets
 34 |     | {
 35 |     |     /// CUSTOM TARGET FUNCTIONS - Add your own target functions here ///
 36 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
 37 |     | }
 38 |     | 

/opt/scfuzzbench/work/target/test/recon/helpers/MerkleTestHelper.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
   5 |     | 
   6 |     | /// @title MerkleTestHelper
   7 |     | /// @notice Helper contract for generating test Merkle roots and proofs for hook validation
   8 | *   | contract MerkleTestHelper {
   9 |     |     /// @notice Generate a test Merkle root for ERC4626 deposit and redeem hooks
  10 |     |     /// @param depositHook Address of the Deposit4626VaultHook or ApproveAndDeposit4626VaultHook contract
  11 |     |     /// @param redeemHook Address of the Redeem4626VaultHook contract  
  12 |     |     /// @param mockVault Address of the mock ERC4626 vault
  13 |     |     /// @param mockToken Address of the mock token (unused but kept for compatibility)
  14 |     |     /// @return root The Merkle root for the tree
  15 |     |     /// @return proofs Array of proofs for each leaf [depositProof, redeemProof]
  16 | *   |     function generateTestHooksRoot(
  17 |     |         address depositHook,
  18 |     |         address redeemHook,
  19 |     |         address mockVault,
  20 |     |         address mockToken
  21 | *   |     ) public pure returns (bytes32 root, bytes32[][] memory proofs) {
  22 |     |         // Create leaves for the two hooks following the exact format from SuperVaultAggregator._createLeaf()
  23 | *   |         bytes32[] memory leaves = new bytes32[](2);
  24 |     |         
  25 |     |         // Leaf 1: Deposit hook with yield source only (what inspect() returns)
  26 |     |         // The inspect() function only returns abi.encodePacked(yieldSource)
  27 | *   |         bytes memory depositArgs = abi.encodePacked(mockVault); // Only yield source address
  28 | *   |         leaves[0] = keccak256(bytes.concat(keccak256(abi.encode(depositHook, depositArgs))));
  29 |     |         
  30 |     |         // Leaf 2: Redeem hook with yield source only (what inspect() returns)
  31 |     |         // The inspect() function only returns abi.encodePacked(yieldSource)
  32 | *   |         bytes memory redeemArgs = abi.encodePacked(mockVault); // Only yield source address
  33 | *   |         leaves[1] = keccak256(bytes.concat(keccak256(abi.encode(redeemHook, redeemArgs))));
  34 |     |         
  35 |     |         // Sort leaves to match standard Merkle tree ordering
  36 | *   |         if (leaves[0] > leaves[1]) {
  37 | *   |             (leaves[0], leaves[1]) = (leaves[1], leaves[0]);
  38 |     |         }
  39 |     |         
  40 |     |         // For a 2-leaf tree, root is hash of the sorted leaves
  41 | *   |         root = keccak256(abi.encodePacked(leaves[0], leaves[1]));
  42 |     |         
  43 |     |         // Store original leaf hashes for proof assignment
  44 | *   |         bytes32 depositLeaf = keccak256(bytes.concat(keccak256(abi.encode(depositHook, depositArgs))));
  45 | *   |         bytes32 redeemLeaf = keccak256(bytes.concat(keccak256(abi.encode(redeemHook, redeemArgs))));
  46 |     |         
  47 |     |         // Generate proofs for each leaf
  48 | *   |         proofs = new bytes32[][](2);
  49 | *   |         proofs[0] = new bytes32[](1); // Proof for deposit hook
  50 | *   |         proofs[1] = new bytes32[](1); // Proof for redeem hook
  51 |     |         
  52 |     |         // In a 2-leaf tree, each leaf's proof is just its sibling
  53 |     |         // Find which position each leaf ended up in after sorting
  54 | *   |         if (leaves[0] == depositLeaf) {
  55 |     |             // depositHook is first leaf after sorting
  56 | *   |             proofs[0][0] = leaves[1]; // Sibling of deposit leaf
  57 | *   |             proofs[1][0] = leaves[0]; // Sibling of redeem leaf  
  58 |     |         } else {
  59 |     |             // redeemHook is first leaf after sorting
  60 | *   |             proofs[0][0] = leaves[1]; // Sibling of deposit leaf
  61 | *   |             proofs[1][0] = leaves[0]; // Sibling of redeem leaf
  62 |     |         }
  63 |     |         
  64 | *   |         return (root, proofs);
  65 |     |     }
  66 |     |     
  67 |     |     /// @notice Generate encoded hook arguments for Deposit4626VaultHook
  68 |     |     /// @param yieldSource Address of the yield source vault
  69 |     |     /// @param amount Amount to deposit
  70 |     |     /// @param usePrevHookAmount Whether to use previous hook amount
  71 |     |     /// @return Encoded hook arguments
  72 |     |     function encodeDepositHookArgs(
  73 |     |         address yieldSource,
  74 |     |         uint256 amount,
  75 |     |         bool usePrevHookAmount
  76 |     |     ) public pure returns (bytes memory) {
  77 |     |         return abi.encodePacked(
  78 |     |             bytes32(0), // yieldSourceOracleId placeholder
  79 |     |             yieldSource,
  80 |     |             amount,
  81 |     |             usePrevHookAmount
  82 |     |         );
  83 |     |     }
  84 |     |     
  85 |     |     /// @notice Generate encoded hook arguments for Redeem4626VaultHook
  86 |     |     /// @param yieldSource Address of the yield source vault
  87 |     |     /// @param owner Address of the owner
  88 |     |     /// @param shares Number of shares to redeem
  89 |     |     /// @param usePrevHookAmount Whether to use previous hook amount
  90 |     |     /// @return Encoded hook arguments
  91 | *   |     function encodeRedeemHookArgs(
  92 |     |         address yieldSource,
  93 |     |         address owner,
  94 |     |         uint256 shares,
  95 |     |         bool usePrevHookAmount
  96 |     |     ) public pure returns (bytes memory) {
  97 |     |         return abi.encodePacked(
  98 |     |             bytes32(0), // yieldSourceOracleId placeholder
  99 |     |             yieldSource,
 100 |     |             owner,
 101 |     |             shares,
 102 |     |             usePrevHookAmount
 103 |     |         );
 104 |     |     }
 105 |     |     
 106 |     |     /// @notice Generate encoded hook arguments for ApproveAndDeposit4626VaultHook
 107 |     |     /// @param yieldSource Address of the yield source vault
 108 |     |     /// @param token Address of the token to approve and deposit
 109 |     |     /// @param amount Amount to deposit
 110 |     |     /// @param usePrevHookAmount Whether to use previous hook amount
 111 |     |     /// @return Encoded hook arguments
 112 |     |     function encodeApproveAndDepositHookArgs(
 113 |     |         address yieldSource,
 114 |     |         address token,
 115 |     |         uint256 amount,
 116 |     |         bool usePrevHookAmount
 117 |     |     ) public pure returns (bytes memory) {
 118 |     |         return abi.encodePacked(
 119 |     |             bytes32(0), // yieldSourceOracleId placeholder
 120 |     |             yieldSource,
 121 |     |             token,
 122 |     |             amount,
 123 |     |             usePrevHookAmount
 124 |     |         );
 125 |     |     }
 126 |     |     
 127 |     |     /// @notice Create a leaf hash for a specific hook and arguments
 128 |     |     /// @param hookAddress Address of the hook contract
 129 |     |     /// @param hookArgs Encoded hook arguments
 130 |     |     /// @return leaf The leaf hash
 131 |     |     function createLeaf(address hookAddress, bytes memory hookArgs) public pure returns (bytes32 leaf) {
 132 |     |         return keccak256(bytes.concat(keccak256(abi.encode(hookAddress, hookArgs))));
 133 |     |     }
 134 |     |     
 135 |     |     /// @notice Verify a Merkle proof against a root
 136 |     |     /// @param proof Array of proof elements
 137 |     |     /// @param root Merkle root
 138 |     |     /// @param leaf Leaf to verify
 139 |     |     /// @return True if proof is valid
 140 | *   |     function verifyProof(bytes32[] memory proof, bytes32 root, bytes32 leaf) public pure returns (bool) {
 141 | *   |         return MerkleProof.verify(proof, root, leaf);
 142 |     |     }
 143 |     | }

/opt/scfuzzbench/work/target/test/recon/helpers/UnsafeSuperVaultAggregator.sol
  1 |     | // SPDX-License-Identifier: UNLICENSED
  2 |     | pragma solidity 0.8.30;
  3 |     | 
  4 |     | import {SuperVaultAggregator} from "src/SuperVault/SuperVaultAggregator.sol";
  5 |     | 
  6 |     | /// @dev inherits from aggregator to override hook validation
  7 | *   | contract UnsafeSuperVaultAggregator is SuperVaultAggregator {
  8 | *   |     constructor(
  9 |     |         address superGovernor_,
 10 |     |         address vaultImpl_,
 11 |     |         address strategyImpl_,
 12 |     |         address escrowImpl_
 13 |     |     )
 14 |     |         SuperVaultAggregator(
 15 | *   |             superGovernor_,
 16 | *   |             vaultImpl_,
 17 | *   |             strategyImpl_,
 18 | *   |             escrowImpl_
 19 |     |         )
 20 |     |     {}
 21 |     | 
 22 | *   |     function validateHook(
 23 |     |         address strategy,
 24 |     |         ValidateHookArgs calldata args
 25 |     |     ) external view override returns (bool isValid) {
 26 | *   |         return true;
 27 |     |     }
 28 |     | }
 29 |     | 

/opt/scfuzzbench/work/target/test/recon/managers/YieldManager.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {BaseSetup} from "@chimera/BaseSetup.sol";
   5 |     | import {vm} from "@chimera/Hevm.sol";
   6 |     | 
   7 |     | import {EnumerableSet} from "@recon/EnumerableSet.sol";
   8 |     | import {MockERC20} from "@recon/MockERC20.sol";
   9 |     | 
  10 |     | import {MockERC4626Tester} from "../mocks/MockERC4626Tester.sol";
  11 |     | import {MockERC5115Tester} from "../mocks/MockERC5115Tester.sol";
  12 |     | import {MockERC7540Tester} from "../mocks/MockERC7540Tester.sol";
  13 |     | 
  14 |     | /// @dev Source of truth for the yield sources being used in the test
  15 |     | /// @notice No yield sources should be used in the test suite without being added from here first
  16 |     | /// @notice Enum to specify the type of yield source to deploy
  17 |     | enum YieldSourceType {
  18 |     |     ERC4626,
  19 |     |     ERC5115,
  20 |     |     ERC7540
  21 |     | }
  22 |     | 
  23 |     | abstract contract YieldManager {
  24 |     |     using EnumerableSet for EnumerableSet.AddressSet;
  25 |     | 
  26 |     |     /// @notice The current target for this set of variables
  27 |     |     address private __yieldSource;
  28 |     | 
  29 |     |     /// @notice The current yield source type
  30 |     |     YieldSourceType private __currentYieldSourceType;
  31 |     | 
  32 |     |     /// @notice The list of all yield sources being used
  33 |     |     EnumerableSet.AddressSet private _yieldSources;
  34 |     | 
  35 |     |     // If the current target is address(0) then it has not been setup yet and should revert
  36 |     |     error YieldSourceNotSetup();
  37 |     |     // Do not allow duplicates
  38 |     |     error YieldSourceExists();
  39 |     |     // Enable only added yield sources
  40 |     |     error YieldSourceNotAdded();
  41 |     |     // Invalid yield source type
  42 |     |     error InvalidYieldSourceType();
  43 |     | 
  44 |     |     /// @notice Returns the current active yield source
  45 | *   |     function _getYieldSource() internal view returns (address) {
  46 | *   |         if (__yieldSource == address(0)) {
  47 |     |             revert YieldSourceNotSetup();
  48 |     |         }
  49 |     | 
  50 | *   |         return __yieldSource;
  51 |     |     }
  52 |     | 
  53 |     |     /// @notice Returns all yield sources being used
  54 | *   |     function _getYieldSources() internal view returns (address[] memory) {
  55 | *   |         return _yieldSources.values();
  56 |     |     }
  57 |     | 
  58 |     |     /// @notice Returns the current yield source type
  59 | *   |     function _getCurrentYieldSourceType() internal view returns (YieldSourceType) {
  60 | *   |         return __currentYieldSourceType;
  61 |     |     }
  62 |     | 
  63 |     |     /// @notice Creates a new yield source and adds it to the list of yield sources
  64 |     |     /// @param asset The asset to create the yield source for
  65 |     |     /// @param yieldSourceType The type of yield source to deploy
  66 |     |     /// @return The address of the new yield source
  67 | *   |     function _newYieldSource(address asset, YieldSourceType yieldSourceType) internal returns (address) {
  68 |     |         address yieldSource_;
  69 |     |         
  70 | *   |         if (yieldSourceType == YieldSourceType.ERC4626) {
  71 | *   |             yieldSource_ = address(new MockERC4626Tester(asset));
  72 | *   |         } else if (yieldSourceType == YieldSourceType.ERC5115) {
  73 | *   |             yieldSource_ = address(new MockERC5115Tester(asset));
  74 | *   |         } else if (yieldSourceType == YieldSourceType.ERC7540) {
  75 | *   |             yieldSource_ = address(new MockERC7540Tester(asset));
  76 |     |         } else {
  77 |     |             revert InvalidYieldSourceType();
  78 |     |         }
  79 |     |         
  80 | *   |         _addYieldSource(yieldSource_);
  81 | *   |         __yieldSource = yieldSource_; // sets the yield source as the current yield source
  82 | *   |         __currentYieldSourceType = yieldSourceType;
  83 | *   |         return yieldSource_;
  84 |     |     }
  85 |     | 
  86 |     |     /// @notice Creates a new yield source with ERC4626 by default (backward compatibility)
  87 |     |     /// @param asset The asset to create the yield source for
  88 |     |     /// @return The address of the new yield source
  89 |     |     function _newYieldSource(address asset) internal returns (address) {
  90 |     |         return _newYieldSource(asset, YieldSourceType.ERC4626);
  91 |     |     }
  92 |     | 
  93 |     |     /// @notice Legacy function name for backward compatibility
  94 |     |     /// @param asset The asset to create the yield source for
  95 |     |     /// @return The address of the new yield source
  96 | *   |     function _newVault(address asset) internal returns (address) {
  97 | *   |         return _newYieldSource(asset, YieldSourceType.ERC4626);
  98 |     |     }
  99 |     | 
 100 |     |     /// @notice Adds a yield source to the list of yield sources
 101 |     |     /// @param target The address of the yield source to add
 102 | *   |     function _addYieldSource(address target) internal {
 103 | *   |         if (_yieldSources.contains(target)) {
 104 |     |             revert YieldSourceExists();
 105 |     |         }
 106 |     | 
 107 | *   |         _yieldSources.add(target);
 108 |     |     }
 109 |     | 
 110 |     |     /// @notice Legacy function name for backward compatibility
 111 |     |     /// @param target The address of the yield source to add
 112 |     |     function _addVault(address target) internal {
 113 |     |         _addYieldSource(target);
 114 |     |     }
 115 |     | 
 116 |     |     /// @notice Removes a yield source from the list of yield sources
 117 |     |     /// @param target The address of the yield source to remove
 118 |     |     function _removeYieldSource(address target) internal {
 119 |     |         if (!_yieldSources.contains(target)) {
 120 |     |             revert YieldSourceNotAdded();
 121 |     |         }
 122 |     | 
 123 |     |         _yieldSources.remove(target);
 124 |     |     }
 125 |     | 
 126 |     |     /// @notice Legacy function name for backward compatibility
 127 |     |     /// @param target The address of the yield source to remove
 128 |     |     function _removeVault(address target) internal {
 129 |     |         _removeYieldSource(target);
 130 |     |     }
 131 |     | 
 132 |     |     /// @notice Switches the current yield source based on the entropy
 133 |     |     /// @param entropy The entropy to choose a random yield source in the array for switching
 134 | *   |     function _switchYieldSource(uint256 entropy) internal {
 135 | *   |         address target = _yieldSources.at(entropy % _yieldSources.length());
 136 | *   |         __yieldSource = target;
 137 |     |     }
 138 |     | 
 139 |     |     /// @notice Legacy function name for backward compatibility
 140 |     |     /// @param entropy The entropy to choose a random yield source in the array for switching
 141 |     |     function _switchVault(uint256 entropy) internal {
 142 |     |         _switchYieldSource(entropy);
 143 |     |     }
 144 |     | 
 145 |     |     /// @notice Switches to a different yield source type by deploying a new yield source
 146 |     |     /// @param asset The asset to create the new yield source for
 147 |     |     /// @param newYieldSourceType The new yield source type to switch to
 148 |     |     /// @return The address of the new yield source
 149 |     |     function _switchYieldSourceType(address asset, YieldSourceType newYieldSourceType) internal returns (address) {
 150 |     |         return _newYieldSource(asset, newYieldSourceType);
 151 |     |     }
 152 |     | }
 153 |     | 

/opt/scfuzzbench/work/target/test/recon/mocks/MockECDSAPPSOracle.sol
   1 |     | // SPDX-License-Identifier: UNLICENSED
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {ISuperVaultAggregator} from "src/interfaces/SuperVault/ISuperVaultAggregator.sol";
   5 |     | import {IECDSAPPSOracle} from "src/interfaces/oracles/IECDSAPPSOracle.sol";
   6 |     | 
   7 | *   | contract MockECDSAPPSOracle {
   8 |     |     //<>=============================================================<>
   9 |     |     //||                                                             ||
  10 |     |     //||                    NON-VIEW FUNCTIONS                       ||
  11 |     |     //||                                                             ||
  12 |     |     //<>=============================================================<>
  13 |     |     // Mock implementation of updatePPS
  14 | *   |     function updatePPS(IECDSAPPSOracle.UpdatePPSArgs memory args) public {
  15 | *   |         ISuperVaultAggregator.ForwardPPSArgs
  16 | *   |             memory forwardArgs = ISuperVaultAggregator.ForwardPPSArgs({
  17 | *   |                 strategies: args.strategies,
  18 | *   |                 ppss: args.ppss,
  19 | *   |                 ppsStdevs: args.ppsStdevs,
  20 | *   |                 validatorSets: args.validatorSets,
  21 | *   |                 totalValidators: args.totalValidators,
  22 | *   |                 timestamps: args.timestamps,
  23 | *   |                 updateAuthority: msg.sender
  24 |     |             });
  25 |     | 
  26 | *   |         ISuperVaultAggregator(_SUPER_GOVERNORReturn_0).forwardPPS(forwardArgs);
  27 |     |     }
  28 |     | 
  29 |     |     //<>=============================================================<>
  30 |     |     //||                                                             ||
  31 |     |     //||                    SETTER FUNCTIONS                         ||
  32 |     |     //||                                                             ||
  33 |     |     //<>=============================================================<>
  34 |     |     // Function to set return values for SUPER_GOVERNOR
  35 | *   |     function setSUPER_GOVERNORReturn(address _value0) public {
  36 | *   |         _SUPER_GOVERNORReturn_0 = _value0;
  37 |     |     }
  38 |     | 
  39 |     |     // Function to set return values for UPDATE_PPS_TYPEHASH
  40 |     |     function setUPDATE_PPS_TYPEHASHReturn(bytes32 _value0) public {
  41 |     |         _UPDATE_PPS_TYPEHASHReturn_0 = _value0;
  42 |     |     }
  43 |     | 
  44 |     |     // Function to set return values for domainSeparator
  45 | *   |     function setDomainSeparatorReturn(bytes32 _value0) public {
  46 |     |         _domainSeparatorReturn_0 = _value0;
  47 |     |     }
  48 |     | 
  49 |     |     /*******************************************************************
  50 |     |      *   ⚠️ WARNING ⚠️ WARNING ⚠️ WARNING ⚠️ WARNING ⚠️ WARNING ⚠️  *
  51 |     |      *-----------------------------------------------------------------*
  52 |     |      *      Generally you only need to modify the sections above.      *
  53 |     |      *          The code below handles system operations.              *
  54 |     |      *******************************************************************/
  55 |     | 
  56 |     |     //<>=============================================================<>
  57 |     |     //||                                                             ||
  58 |     |     //||        ⚠️  STRUCT DEFINITIONS - DO NOT MODIFY  ⚠️          ||
  59 |     |     //||                                                             ||
  60 |     |     //<>=============================================================<>
  61 |     |     // Struct definition removed - using IECDSAPPSOracle.UpdatePPSArgs from interface
  62 |     | 
  63 |     |     //<>=============================================================<>
  64 |     |     //||                                                             ||
  65 |     |     //||        ⚠️  EVENTS DEFINITIONS - DO NOT MODIFY  ⚠️          ||
  66 |     |     //||                                                             ||
  67 |     |     //<>=============================================================<>
  68 |     |     event EIP712DomainChanged();
  69 |     |     event PPSValidated(
  70 |     |         address strategy,
  71 |     |         uint256 pps,
  72 |     |         uint256 ppsStdev,
  73 |     |         uint256 validatorSet,
  74 |     |         uint256 totalValidators,
  75 |     |         uint256 timestamp,
  76 |     |         address sender
  77 |     |     );
  78 |     | 
  79 |     |     //<>=============================================================<>
  80 |     |     //||                                                             ||
  81 |     |     //||         ⚠️  INTERNAL STORAGE - DO NOT MODIFY  ⚠️           ||
  82 |     |     //||                                                             ||
  83 |     |     //<>=============================================================<>
  84 |     |     address private _SUPER_GOVERNORReturn_0;
  85 |     |     bytes32 private _UPDATE_PPS_TYPEHASHReturn_0;
  86 |     |     bytes32 private _domainSeparatorReturn_0;
  87 |     |     bytes1 private _eip712DomainReturn_0;
  88 |     |     string private _eip712DomainReturn_1;
  89 |     |     string private _eip712DomainReturn_2;
  90 |     |     uint256 private _eip712DomainReturn_3;
  91 |     |     address private _eip712DomainReturn_4;
  92 |     |     bytes32 private _eip712DomainReturn_5;
  93 |     |     uint256[] private _eip712DomainReturn_6;
  94 |     |     uint256 private _nonceReturn_0;
  95 |     | 
  96 |     |     //<>=============================================================<>
  97 |     |     //||                                                             ||
  98 |     |     //||          ⚠️  VIEW FUNCTIONS - DO NOT MODIFY  ⚠️            ||
  99 |     |     //||                                                             ||
 100 |     |     //<>=============================================================<>
 101 |     |     // Mock implementation of SUPER_GOVERNOR
 102 |     |     function SUPER_GOVERNOR() public view returns (address) {
 103 |     |         return _SUPER_GOVERNORReturn_0;
 104 |     |     }
 105 |     | 
 106 |     |     // Mock implementation of UPDATE_PPS_TYPEHASH
 107 |     |     function UPDATE_PPS_TYPEHASH() public view returns (bytes32) {
 108 |     |         return _UPDATE_PPS_TYPEHASHReturn_0;
 109 |     |     }
 110 |     | 
 111 |     |     // Mock implementation of domainSeparator
 112 |     |     function domainSeparator() public view returns (bytes32) {
 113 |     |         return _domainSeparatorReturn_0;
 114 |     |     }
 115 |     | 
 116 |     |     // Mock implementation of eip712Domain
 117 |     |     function eip712Domain()
 118 |     |         public
 119 |     |         view
 120 |     |         returns (
 121 |     |             bytes1,
 122 |     |             string memory,
 123 |     |             string memory,
 124 |     |             uint256,
 125 |     |             address,
 126 |     |             bytes32,
 127 |     |             uint256[] memory
 128 |     |         )
 129 |     |     {
 130 |     |         return (
 131 |     |             _eip712DomainReturn_0,
 132 |     |             _eip712DomainReturn_1,
 133 |     |             _eip712DomainReturn_2,
 134 |     |             _eip712DomainReturn_3,
 135 |     |             _eip712DomainReturn_4,
 136 |     |             _eip712DomainReturn_5,
 137 |     |             _eip712DomainReturn_6
 138 |     |         );
 139 |     |     }
 140 |     | 
 141 |     |     // Mock implementation of nonce
 142 |     |     function nonce() public view returns (uint256) {
 143 |     |         return _nonceReturn_0;
 144 |     |     }
 145 |     | }
 146 |     | 

/opt/scfuzzbench/work/target/test/recon/mocks/MockERC4626Tester.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | // Heavily inspired by https://github.com/liquity/V2-gov/blob/9632de9a988522775336d9b60cdf2542efc600db/test/mocks/MaliciousInitiative.sol
   3 |     | pragma solidity ^0.8.0;
   4 |     | 
   5 |     | import {MockERC20} from "@recon/MockERC20.sol";
   6 |     | 
   7 |     | abstract contract ERC4626 is MockERC20 {
   8 | *   |     MockERC20 public immutable asset;
   9 |     | 
  10 |     |     event Deposit(
  11 |     |         address indexed caller,
  12 |     |         address indexed owner,
  13 |     |         uint256 assets,
  14 |     |         uint256 shares
  15 |     |     );
  16 |     |     event Withdraw(
  17 |     |         address indexed caller,
  18 |     |         address indexed receiver,
  19 |     |         address indexed owner,
  20 |     |         uint256 assets,
  21 |     |         uint256 shares
  22 |     |     );
  23 |     | 
  24 | *   |     constructor(MockERC20 _asset) MockERC20("MockERC4626Tester", "MCT", 18) {
  25 | *   |         asset = _asset;
  26 |     |     }
  27 |     | 
  28 | *   |     function deposit(
  29 |     |         uint256 assets,
  30 |     |         address receiver
  31 | *   |     ) public virtual returns (uint256) {
  32 | *   |         uint256 shares = previewDeposit(assets);
  33 | *   |         _deposit(msg.sender, receiver, assets, shares);
  34 |     |         return shares;
  35 |     |     }
  36 |     | 
  37 | *   |     function mint(
  38 |     |         uint256 shares,
  39 |     |         address receiver
  40 | *   |     ) public virtual returns (uint256) {
  41 | *   |         uint256 assets = previewMint(shares);
  42 | *   |         _deposit(msg.sender, receiver, assets, shares);
  43 |     |         return assets;
  44 |     |     }
  45 |     | 
  46 |     |     function withdraw(
  47 |     |         uint256 assets,
  48 |     |         address receiver,
  49 |     |         address owner
  50 |     |     ) public virtual returns (uint256) {
  51 |     |         uint256 shares = previewWithdraw(assets);
  52 |     |         _withdraw(msg.sender, receiver, owner, assets, shares);
  53 |     |         return shares;
  54 |     |     }
  55 |     | 
  56 |     |     function redeem(
  57 |     |         uint256 shares,
  58 |     |         address receiver,
  59 |     |         address owner
  60 |     |     ) public virtual returns (uint256) {
  61 |     |         uint256 assets = previewRedeem(shares);
  62 |     |         _withdraw(msg.sender, receiver, owner, assets, shares);
  63 |     |         return assets;
  64 |     |     }
  65 |     | 
  66 | *   |     function totalAssets() public view virtual returns (uint256) {
  67 | *   |         return asset.balanceOf(address(this));
  68 |     |     }
  69 |     | 
  70 | *   |     function convertToShares(
  71 |     |         uint256 assets
  72 | *   |     ) public view virtual returns (uint256) {
  73 | *   |         uint256 supply = totalSupply;
  74 | *   |         return supply == 0 ? assets : (assets * supply) / totalAssets();
  75 |     |     }
  76 |     | 
  77 | *   |     function convertToAssets(
  78 |     |         uint256 shares
  79 | *   |     ) public view virtual returns (uint256) {
  80 | *   |         uint256 supply = totalSupply;
  81 | *   |         return supply == 0 ? shares : (shares * totalAssets()) / supply;
  82 |     |     }
  83 |     | 
  84 | *   |     function previewDeposit(
  85 |     |         uint256 assets
  86 | *   |     ) public view virtual returns (uint256) {
  87 | *   |         return convertToShares(assets);
  88 |     |     }
  89 |     | 
  90 |     |     function previewMint(uint256 shares) public view virtual returns (uint256) {
  91 |     |         uint256 supply = totalSupply;
  92 |     |         return supply == 0 ? shares : (shares * totalAssets()) / supply;
  93 |     |     }
  94 |     | 
  95 |     |     function previewWithdraw(
  96 |     |         uint256 assets
  97 |     |     ) public view virtual returns (uint256) {
  98 |     |         uint256 supply = totalSupply;
  99 |     |         return supply == 0 ? assets : (assets * supply) / totalAssets();
 100 |     |     }
 101 |     | 
 102 | *   |     function previewRedeem(
 103 |     |         uint256 shares
 104 | *   |     ) public view virtual returns (uint256) {
 105 | *   |         return convertToAssets(shares);
 106 |     |     }
 107 |     | 
 108 | *   |     function maxDeposit(address) public view virtual returns (uint256) {
 109 | *   |         return type(uint256).max;
 110 |     |     }
 111 |     | 
 112 |     |     function maxMint(address) public view virtual returns (uint256) {
 113 |     |         return type(uint256).max;
 114 |     |     }
 115 |     | 
 116 | *   |     function maxWithdraw(address owner) public view virtual returns (uint256) {
 117 | *   |         return convertToAssets(balanceOf[owner]);
 118 |     |     }
 119 |     | 
 120 | *   |     function maxRedeem(address owner) public view virtual returns (uint256) {
 121 | *   |         return balanceOf[owner];
 122 |     |     }
 123 |     | 
 124 | *   |     function _deposit(
 125 |     |         address caller,
 126 |     |         address receiver,
 127 |     |         uint256 assets,
 128 |     |         uint256 shares
 129 |     |     ) internal virtual {
 130 | *   |         asset.transferFrom(caller, address(this), assets);
 131 | *   |         _mint(receiver, shares);
 132 | *   |         emit Deposit(caller, receiver, assets, shares);
 133 |     |     }
 134 |     | 
 135 | *   |     function _withdraw(
 136 |     |         address caller,
 137 |     |         address receiver,
 138 |     |         address owner,
 139 |     |         uint256 assets,
 140 |     |         uint256 shares
 141 |     |     ) internal virtual {
 142 | *   |         if (caller != owner) {
 143 | *   |             allowance[owner][caller] -= shares;
 144 |     |         }
 145 | *   |         _burn(owner, shares);
 146 | *   |         asset.transfer(receiver, assets);
 147 | *   |         emit Withdraw(caller, receiver, owner, assets, shares);
 148 |     |     }
 149 |     | }
 150 |     | 
 151 |     | enum FunctionType {
 152 |     |     NONE,
 153 |     |     DEPOSIT,
 154 |     |     MINT,
 155 |     |     WITHDRAW,
 156 |     |     REDEEM
 157 |     | }
 158 |     | 
 159 |     | enum RevertType {
 160 |     |     NONE,
 161 |     |     THROW,
 162 |     |     OOG,
 163 |     |     RETURN_BOMB,
 164 |     |     REVERT_BOMB
 165 |     | }
 166 |     | 
 167 |     | /// @dev This will use the simplest possible implementation initially to allow getting coverage and will be expanded on as necessary for testing potentially more interesting behaviors
 168 |     | /// @dev Note that blindspots not testable with this current implementation are covered in the ERC4626-integrations.md file
 169 | *   | contract MockERC4626Tester is ERC4626 {
 170 |     |     mapping(FunctionType => RevertType) public revertBehaviours;
 171 |     | 
 172 |     |     uint8 public decimalsOffset;
 173 |     |     /// @dev Track total losses
 174 |     |     uint256 public totalLosses;
 175 |     |     uint256 public totalGains;
 176 |     |     uint256 public lossOnWithdraw;
 177 | *   |     uint256 public MAX_BPS = 10_000;
 178 |     | 
 179 | *   |     constructor(address _asset) ERC4626(MockERC20(_asset)) {}
 180 |     | 
 181 |     |     /// Standard ERC4626 functions ///
 182 |     | 
 183 |     |     /// @dev Deposit assets, reverts as specified
 184 | *   |     function deposit(
 185 |     |         uint256 assets,
 186 |     |         address receiver
 187 | *   |     ) public override returns (uint256) {
 188 | *   |         _performRevertBehaviour(revertBehaviours[FunctionType.DEPOSIT]);
 189 | *   |         return super.deposit(assets, receiver);
 190 |     |     }
 191 |     | 
 192 |     |     /// @dev Mint shares, reverts as specified
 193 | *   |     function mint(
 194 |     |         uint256 shares,
 195 |     |         address receiver
 196 | *   |     ) public override returns (uint256) {
 197 | *   |         _performRevertBehaviour(revertBehaviours[FunctionType.MINT]);
 198 | *   |         return super.mint(shares, receiver);
 199 |     |     }
 200 |     | 
 201 |     |     /// @dev Withdraw assets, reverts as specified
 202 | *   |     function withdraw(
 203 |     |         uint256 assets,
 204 |     |         address receiver,
 205 |     |         address owner
 206 | *   |     ) public override returns (uint256) {
 207 | *   |         _performRevertBehaviour(revertBehaviours[FunctionType.WITHDRAW]);
 208 |     | 
 209 | *   |         uint256 shares = previewWithdraw(assets);
 210 | *   |         uint256 lossyAssets = assets - ((assets * lossOnWithdraw) / MAX_BPS);
 211 | *   |         _withdraw(msg.sender, receiver, owner, lossyAssets, shares);
 212 |     | 
 213 | *   |         return shares;
 214 |     |     }
 215 |     | 
 216 |     |     /// @dev Redeem shares, reverts as specified
 217 | *   |     function redeem(
 218 |     |         uint256 shares,
 219 |     |         address receiver,
 220 |     |         address owner
 221 | *   |     ) public override returns (uint256) {
 222 | *   |         _performRevertBehaviour(revertBehaviours[FunctionType.REDEEM]);
 223 |     | 
 224 | *   |         uint256 assets = previewRedeem(shares);
 225 | *   |         uint256 lossyAssets = assets - ((assets * lossOnWithdraw) / MAX_BPS);
 226 | *   |         _withdraw(msg.sender, receiver, owner, lossyAssets, shares);
 227 |     | 
 228 | *   |         return lossyAssets;
 229 |     |     }
 230 |     | 
 231 |     |     /// @dev Preview deposit, reverts as specified
 232 | *   |     function previewDeposit(
 233 |     |         uint256 assets
 234 | *   |     ) public view override returns (uint256) {
 235 | *   |         _performRevertBehaviour(revertBehaviours[FunctionType.DEPOSIT]);
 236 | *   |         return super.previewDeposit(assets);
 237 |     |     }
 238 |     | 
 239 |     |     /// @dev Preview mint, reverts as specified
 240 | *   |     function previewMint(
 241 |     |         uint256 shares
 242 | *   |     ) public view override returns (uint256) {
 243 | *   |         _performRevertBehaviour(revertBehaviours[FunctionType.MINT]);
 244 | *   |         return super.previewMint(shares);
 245 |     |     }
 246 |     | 
 247 |     |     /// @dev Preview withdraw, reverts as specified
 248 | *   |     function previewWithdraw(
 249 |     |         uint256 assets
 250 | *   |     ) public view override returns (uint256) {
 251 | *   |         _performRevertBehaviour(revertBehaviours[FunctionType.WITHDRAW]);
 252 | *   |         return super.previewWithdraw(assets);
 253 |     |     }
 254 |     | 
 255 |     |     /// @dev Preview redeem, reverts as specified
 256 | *   |     function previewRedeem(
 257 |     |         uint256 shares
 258 | *   |     ) public view override returns (uint256) {
 259 | *   |         _performRevertBehaviour(revertBehaviours[FunctionType.REDEEM]);
 260 | *   |         return super.previewRedeem(shares);
 261 |     |     }
 262 |     | 
 263 |     |     /// @dev Revert in different ways to test the revert behaviour
 264 | *   |     function _performRevertBehaviour(RevertType action) internal pure {
 265 | *   |         if (action == RevertType.THROW) {
 266 | *   |             revert("A normal Revert");
 267 |     |         }
 268 |     | 
 269 |     |         // 3 gas per iteration, consider changing to storage changes if traces are cluttered
 270 | *   |         if (action == RevertType.OOG) {
 271 |     |             uint256 i;
 272 |     |             while (true) {
 273 |     |                 ++i;
 274 |     |             }
 275 |     |         }
 276 |     | 
 277 | *   |         if (action == RevertType.RETURN_BOMB) {
 278 |     |             uint256 _bytes = 2_000_000;
 279 |     |             assembly {
 280 |     |                 return(0, _bytes)
 281 |     |             }
 282 |     |         }
 283 |     | 
 284 | *   |         if (action == RevertType.REVERT_BOMB) {
 285 |     |             uint256 _bytes = 2_000_000;
 286 |     |             assembly {
 287 |     |                 revert(0, _bytes)
 288 |     |             }
 289 |     |         }
 290 |     | 
 291 |     |         return; // NONE
 292 |     |     }
 293 |     | 
 294 |     |     /// Custom functions for testing vault behavior ///
 295 |     | 
 296 |     |     /// @dev Specify the revert behavior on each function
 297 | *   |     function setRevertBehavior(FunctionType ft, RevertType rt) public {
 298 | *   |         revertBehaviours[ft] = rt;
 299 |     |     }
 300 |     | 
 301 |     |     /// @dev Simulate a loss on the vault's assets
 302 | *   |     function simulateLoss(uint256 lossAmount) external {
 303 | *   |         MockERC20(asset).transfer(address(0xbeef), lossAmount);
 304 | *   |         totalLosses += lossAmount;
 305 |     |     }
 306 |     | 
 307 |     |     /// @dev Simulate a gain on the vault's assets (similar to Yearn's profit taking)
 308 | *   |     function simulateGain(uint256 gainAmount) external {
 309 | *   |         MockERC20(asset).transferFrom(msg.sender, address(this), gainAmount);
 310 | *   |         totalGains += gainAmount;
 311 |     |     }
 312 |     | 
 313 |     |     /// @dev Set the loss on withdraw as percentage of the assets being withdrawn
 314 | *   |     function setLossOnWithdraw(uint256 _lossOnWithdraw) public {
 315 | *   |         _lossOnWithdraw %= MAX_BPS + 1; // clamp to ensure we set a max of 100%
 316 | *   |         lossOnWithdraw = _lossOnWithdraw;
 317 |     |     }
 318 |     | 
 319 |     |     /// @dev Set the decimal offset. Only possible with no supply.
 320 | *   |     function setDecimalsOffset(uint8 targetDecimalsOffset) external {
 321 | *   |         if (totalSupply != 0) {
 322 | *   |             revert("Supply is not zero");
 323 |     |         }
 324 | *   |         decimalsOffset = targetDecimalsOffset;
 325 |     |     }
 326 |     | }
 327 |     | 

/opt/scfuzzbench/work/target/test/recon/mocks/MockERC4626YieldSourceOracle.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | pragma solidity ^0.8.30;
   3 |     | 
   4 |     | import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
   5 |     | import {IYieldSourceOracle} from "@superform-v2-core/src/interfaces/accounting/IYieldSourceOracle.sol";
   6 |     | 
   7 |     | /// @title MockERC4626YieldSourceOracle
   8 |     | /// @notice Mock oracle for ERC4626 vaults in testing
   9 | *   | contract MockERC4626YieldSourceOracle is IYieldSourceOracle {
  10 |     |     mapping(address => bool) public validAssetMap;
  11 |     |     
  12 | *   |     function setValidAsset(address asset, bool isValid) external {
  13 | *   |         validAssetMap[asset] = isValid;
  14 |     |     }
  15 |     |     
  16 |     |     function decimals(address yieldSourceAddress) external view returns (uint8) {
  17 |     |         return IERC4626(yieldSourceAddress).decimals();
  18 |     |     }
  19 |     |     
  20 | *   |     function getShareOutput(
  21 |     |         address yieldSourceAddress,
  22 |     |         address,
  23 |     |         uint256 assetsIn
  24 | *   |     ) external view returns (uint256) {
  25 | *   |         return IERC4626(yieldSourceAddress).previewDeposit(assetsIn);
  26 |     |     }
  27 |     |     
  28 |     |     function getAssetOutput(
  29 |     |         address yieldSourceAddress,
  30 |     |         address,
  31 |     |         uint256 sharesIn
  32 |     |     ) public view returns (uint256) {
  33 |     |         return IERC4626(yieldSourceAddress).previewRedeem(sharesIn);
  34 |     |     }
  35 |     |     
  36 |     |     function getPricePerShare(address yieldSourceAddress) external view returns (uint256) {
  37 |     |         IERC4626 yieldSource = IERC4626(yieldSourceAddress);
  38 |     |         uint256 _decimals = yieldSource.decimals();
  39 |     |         return yieldSource.convertToAssets(10 ** _decimals);
  40 |     |     }
  41 |     |     
  42 |     |     function getBalanceOfOwner(
  43 |     |         address yieldSourceAddress,
  44 |     |         address ownerOfShares
  45 |     |     ) external view returns (uint256) {
  46 |     |         return IERC4626(yieldSourceAddress).balanceOf(ownerOfShares);
  47 |     |     }
  48 |     |     
  49 |     |     function getTVLByOwnerOfShares(
  50 |     |         address yieldSourceAddress,
  51 |     |         address ownerOfShares
  52 |     |     ) external view returns (uint256) {
  53 |     |         uint256 shares = IERC4626(yieldSourceAddress).balanceOf(ownerOfShares);
  54 |     |         return IERC4626(yieldSourceAddress).convertToAssets(shares);
  55 |     |     }
  56 |     |     
  57 |     |     function getTVL(address yieldSourceAddress) external view returns (uint256) {
  58 |     |         return IERC4626(yieldSourceAddress).totalAssets();
  59 |     |     }
  60 |     |     
  61 |     |     function getPricePerShareMultiple(
  62 |     |         address[] memory yieldSourceAddresses
  63 |     |     ) external view returns (uint256[] memory) {
  64 |     |         uint256[] memory prices = new uint256[](yieldSourceAddresses.length);
  65 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  66 |     |             IERC4626 yieldSource = IERC4626(yieldSourceAddresses[i]);
  67 |     |             uint256 _decimals = yieldSource.decimals();
  68 |     |             prices[i] = yieldSource.convertToAssets(10 ** _decimals);
  69 |     |         }
  70 |     |         return prices;
  71 |     |     }
  72 |     |     
  73 |     |     function getTVLByOwnerOfSharesMultiple(
  74 |     |         address[] memory yieldSourceAddresses,
  75 |     |         address[][] memory ownersOfShares
  76 |     |     ) external view returns (uint256[][] memory) {
  77 |     |         uint256[][] memory result = new uint256[][](yieldSourceAddresses.length);
  78 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  79 |     |             result[i] = new uint256[](ownersOfShares[i].length);
  80 |     |             for (uint256 j = 0; j < ownersOfShares[i].length; j++) {
  81 |     |                 uint256 shares = IERC4626(yieldSourceAddresses[i]).balanceOf(ownersOfShares[i][j]);
  82 |     |                 result[i][j] = IERC4626(yieldSourceAddresses[i]).convertToAssets(shares);
  83 |     |             }
  84 |     |         }
  85 |     |         return result;
  86 |     |     }
  87 |     |     
  88 |     |     function getTVLMultiple(
  89 |     |         address[] memory yieldSourceAddresses
  90 |     |     ) external view returns (uint256[] memory) {
  91 |     |         uint256[] memory tvls = new uint256[](yieldSourceAddresses.length);
  92 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  93 |     |             tvls[i] = IERC4626(yieldSourceAddresses[i]).totalAssets();
  94 |     |         }
  95 |     |         return tvls;
  96 |     |     }
  97 |     |     
  98 |     |     function isValidUnderlyingAsset(address, address asset) external view returns (bool) {
  99 |     |         return validAssetMap[asset];
 100 |     |     }
 101 |     |     
 102 |     |     function isValidUnderlyingAssets(
 103 |     |         address[] memory,
 104 |     |         address[] memory assets
 105 |     |     ) external view returns (bool[] memory) {
 106 |     |         bool[] memory validities = new bool[](assets.length);
 107 |     |         for (uint256 i = 0; i < assets.length; i++) {
 108 |     |             validities[i] = validAssetMap[assets[i]];
 109 |     |         }
 110 |     |         return validities;
 111 |     |     }
 112 |     |     
 113 |     |     function getAssetOutputWithFees(
 114 |     |         bytes32,
 115 |     |         address yieldSourceAddress,
 116 |     |         address,
 117 |     |         address,
 118 |     |         uint256 sharesIn
 119 |     |     ) external view returns (uint256) {
 120 |     |         return IERC4626(yieldSourceAddress).previewRedeem(sharesIn);
 121 |     |     }
 122 |     | }

/opt/scfuzzbench/work/target/test/recon/mocks/MockERC5115Tester.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {MockERC20} from "@recon/MockERC20.sol";
   5 |     | 
   6 |     | abstract contract ERC5115 is MockERC20 {
   7 |     |     MockERC20 public immutable yieldToken;
   8 |     |     address[] public tokensIn;
   9 |     |     address[] public tokensOut;
  10 |     | 
  11 |     |     event Deposit(
  12 |     |         address indexed caller,
  13 |     |         address indexed receiver,
  14 |     |         address indexed tokenIn,
  15 |     |         uint256 amountDeposited,
  16 |     |         uint256 amountSyOut
  17 |     |     );
  18 |     | 
  19 |     |     event Redeem(
  20 |     |         address indexed caller,
  21 |     |         address indexed receiver,
  22 |     |         address indexed tokenOut,
  23 |     |         uint256 amountSyToRedeem,
  24 |     |         uint256 amountTokenOut
  25 |     |     );
  26 |     | 
  27 |     |     constructor(
  28 |     |         MockERC20 _yieldToken
  29 | *   |     ) MockERC20("MockERC5115Tester", "SY5115", 18) {
  30 | *   |         yieldToken = _yieldToken;
  31 | *   |         tokensIn.push(address(_yieldToken));
  32 | *   |         tokensOut.push(address(_yieldToken));
  33 |     |     }
  34 |     | 
  35 |     |     function deposit(
  36 |     |         address receiver,
  37 |     |         address tokenIn,
  38 |     |         uint256 amountTokenToDeposit,
  39 |     |         uint256 minSharesOut,
  40 |     |         bool depositFromInternalBalance
  41 |     |     ) public virtual returns (uint256 amountSharesOut) {
  42 |     |         amountSharesOut = previewDeposit(tokenIn, amountTokenToDeposit);
  43 |     | 
  44 |     |         MockERC20(tokenIn).transferFrom(
  45 |     |             msg.sender,
  46 |     |             address(this),
  47 |     |             amountTokenToDeposit
  48 |     |         );
  49 |     |         _mint(receiver, amountSharesOut);
  50 |     | 
  51 |     |         emit Deposit(
  52 |     |             msg.sender,
  53 |     |             receiver,
  54 |     |             tokenIn,
  55 |     |             amountTokenToDeposit,
  56 |     |             amountSharesOut
  57 |     |         );
  58 |     |     }
  59 |     | 
  60 |     |     function exchangeRate() public view virtual returns (uint256) {
  61 |     |         uint256 supply = totalSupply;
  62 |     |         if (supply == 0) return 1e18;
  63 |     |         return (yieldToken.balanceOf(address(this)) * 1e18) / supply;
  64 |     |     }
  65 |     | 
  66 |     |     function getTokensIn() public view virtual returns (address[] memory) {
  67 |     |         return tokensIn;
  68 |     |     }
  69 |     | 
  70 |     |     function getTokensOut() public view virtual returns (address[] memory) {
  71 |     |         return tokensOut;
  72 |     |     }
  73 |     | 
  74 | *   |     function previewDeposit(
  75 |     |         address tokenIn,
  76 |     |         uint256 amountTokenToDeposit
  77 | *   |     ) public view virtual returns (uint256 amountSharesOut) {
  78 | *   |         require(tokenIn == address(yieldToken), "Invalid token");
  79 | *   |         uint256 supply = totalSupply;
  80 | *   |         if (supply == 0) {
  81 | *   |             return amountTokenToDeposit;
  82 |     |         }
  83 |     |         return
  84 |     |             (amountTokenToDeposit * supply) /
  85 |     |             yieldToken.balanceOf(address(this));
  86 |     |     }
  87 |     | 
  88 |     |     function previewRedeem(
  89 |     |         address tokenOut,
  90 |     |         uint256 amountSharesToRedeem
  91 |     |     ) public view virtual returns (uint256 amountTokenOut) {
  92 |     |         require(tokenOut == address(yieldToken), "Invalid token");
  93 |     |         uint256 supply = totalSupply;
  94 |     |         if (supply == 0) {
  95 |     |             return amountSharesToRedeem;
  96 |     |         }
  97 |     |         return
  98 |     |             (amountSharesToRedeem * yieldToken.balanceOf(address(this))) /
  99 |     |             supply;
 100 |     |     }
 101 |     | }
 102 |     | 
 103 |     | enum RevertType {
 104 |     |     NONE,
 105 |     |     THROW,
 106 |     |     OOG,
 107 |     |     RETURN_BOMB,
 108 |     |     REVERT_BOMB
 109 |     | }
 110 |     | 
 111 | *   | contract MockERC5115Tester is ERC5115 {
 112 |     |     RevertType public revertBehaviour;
 113 |     |     uint256 public totalLosses;
 114 |     |     uint256 public totalGains;
 115 |     |     uint256 public lossOnWithdraw;
 116 | *   |     uint256 public MAX_BPS = 10_000;
 117 |     | 
 118 | *   |     constructor(address _yieldToken) ERC5115(MockERC20(_yieldToken)) {}
 119 |     | 
 120 |     |     function deposit(
 121 |     |         address receiver,
 122 |     |         address tokenIn,
 123 |     |         uint256 amountTokenToDeposit,
 124 |     |         uint256 minSharesOut,
 125 |     |         bool depositFromInternalBalance
 126 |     |     ) public override returns (uint256 amountSharesOut) {
 127 |     |         _performRevertBehaviour(revertBehaviour);
 128 |     |         return
 129 |     |             super.deposit(
 130 |     |                 receiver,
 131 |     |                 tokenIn,
 132 |     |                 amountTokenToDeposit,
 133 |     |                 minSharesOut,
 134 |     |                 depositFromInternalBalance
 135 |     |             );
 136 |     |     }
 137 |     | 
 138 |     |     function redeem(
 139 |     |         address receiver,
 140 |     |         uint256 amountSharesToRedeem,
 141 |     |         address tokenOut,
 142 |     |         uint256 minTokenOut,
 143 |     |         bool burnFromInternalBalance
 144 |     |     ) public virtual returns (uint256 amountTokenOut) {
 145 |     |         amountTokenOut = previewRedeem(tokenOut, amountSharesToRedeem);
 146 |     | 
 147 |     |         _burn(msg.sender, amountSharesToRedeem);
 148 |     |         uint256 lossyAmountTokenOut = amountTokenOut -
 149 |     |             ((amountTokenOut * lossOnWithdraw) / MAX_BPS);
 150 |     |         MockERC20(tokenOut).transfer(receiver, lossyAmountTokenOut);
 151 |     | 
 152 |     |         emit Redeem(
 153 |     |             msg.sender,
 154 |     |             receiver,
 155 |     |             tokenOut,
 156 |     |             amountSharesToRedeem,
 157 |     |             amountTokenOut
 158 |     |         );
 159 |     |     }
 160 |     | 
 161 | *   |     function _performRevertBehaviour(RevertType action) internal pure {
 162 |     |         if (action == RevertType.THROW) {
 163 |     |             revert("A normal Revert");
 164 |     |         }
 165 |     | 
 166 |     |         if (action == RevertType.OOG) {
 167 |     |             uint256 i;
 168 |     |             while (true) {
 169 |     |                 ++i;
 170 |     |             }
 171 |     |         }
 172 |     | 
 173 |     |         if (action == RevertType.RETURN_BOMB) {
 174 |     |             uint256 _bytes = 2_000_000;
 175 |     |             assembly {
 176 |     |                 return(0, _bytes)
 177 |     |             }
 178 |     |         }
 179 |     | 
 180 | *   |         if (action == RevertType.REVERT_BOMB) {
 181 |     |             uint256 _bytes = 2_000_000;
 182 |     |             assembly {
 183 |     |                 revert(0, _bytes)
 184 |     |             }
 185 |     |         }
 186 |     | 
 187 |     |         return; // NONE
 188 |     |     }
 189 |     | 
 190 |     |     function setRevertBehavior(RevertType rt) public {
 191 |     |         revertBehaviour = rt;
 192 |     |     }
 193 |     | 
 194 | *   |     function simulateLoss(uint256 lossAmount) external {
 195 | *   |         MockERC20(yieldToken).transfer(address(0xbeef), lossAmount);
 196 | *   |         totalLosses += lossAmount;
 197 |     |     }
 198 |     | 
 199 | *   |     function simulateGain(uint256 gainAmount) external {
 200 | *   |         MockERC20(yieldToken).transferFrom(
 201 | *   |             msg.sender,
 202 | *   |             address(this),
 203 |     |             gainAmount
 204 |     |         );
 205 | *   |         totalGains += gainAmount;
 206 |     |     }
 207 |     | 
 208 |     |     /// @dev Set the loss on withdraw as percentage of the assets being withdrawn
 209 | *   |     function setLossOnWithdraw(uint256 _lossOnWithdraw) public {
 210 | *   |         _lossOnWithdraw %= MAX_BPS + 1; // clamp to ensure we set a max of 100%
 211 | *   |         lossOnWithdraw = _lossOnWithdraw;
 212 |     |     }
 213 |     | 
 214 |     |     function increaseYield(uint256 increasePercentageFP4) public {
 215 |     |         require(increasePercentageFP4 <= 10000, "Invalid percentage");
 216 |     |         uint256 amount = (yieldToken.balanceOf(address(this)) *
 217 |     |             increasePercentageFP4) / 10000;
 218 |     |         MockERC20(yieldToken).transferFrom(msg.sender, address(this), amount);
 219 |     |     }
 220 |     | 
 221 |     |     function decreaseYield(uint256 decreasePercentageFP4) public {
 222 |     |         require(decreasePercentageFP4 <= 10000, "Invalid percentage");
 223 |     |         uint256 amount = (yieldToken.balanceOf(address(this)) *
 224 |     |             decreasePercentageFP4) / 10000;
 225 |     |         MockERC20(yieldToken).transfer(address(0xbeef), amount);
 226 |     |         totalLosses += amount;
 227 |     |     }
 228 |     | }
 229 |     | 

/opt/scfuzzbench/work/target/test/recon/mocks/MockERC5115YieldSourceOracle.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | pragma solidity ^0.8.30;
   3 |     | 
   4 |     | import {IYieldSourceOracle} from "@superform-v2-core/src/interfaces/accounting/IYieldSourceOracle.sol";
   5 |     | import {MockERC5115Tester} from "./MockERC5115Tester.sol";
   6 |     | 
   7 |     | /// @title MockERC5115YieldSourceOracle
   8 |     | /// @notice Mock oracle for ERC5115 (Standardized Yield) vaults in testing
   9 | *   | contract MockERC5115YieldSourceOracle is IYieldSourceOracle {
  10 |     |     mapping(address => bool) public validAssetMap;
  11 |     |     
  12 | *   |     function setValidAsset(address asset, bool isValid) external {
  13 | *   |         validAssetMap[asset] = isValid;
  14 |     |     }
  15 |     |     
  16 |     |     function decimals(address) external pure returns (uint8) {
  17 |     |         // ERC5115 always uses 18 decimals
  18 |     |         return 18;
  19 |     |     }
  20 |     |     
  21 | *   |     function getShareOutput(
  22 |     |         address yieldSourceAddress,
  23 |     |         address assetIn,
  24 |     |         uint256 assetsIn
  25 | *   |     ) external view returns (uint256) {
  26 | *   |         return MockERC5115Tester(yieldSourceAddress).previewDeposit(assetIn, assetsIn);
  27 |     |     }
  28 |     |     
  29 |     |     function getAssetOutput(
  30 |     |         address yieldSourceAddress,
  31 |     |         address assetOut,
  32 |     |         uint256 sharesIn
  33 |     |     ) public view returns (uint256) {
  34 |     |         return MockERC5115Tester(yieldSourceAddress).previewRedeem(assetOut, sharesIn);
  35 |     |     }
  36 |     |     
  37 |     |     function getPricePerShare(address yieldSourceAddress) external view returns (uint256) {
  38 |     |         return MockERC5115Tester(yieldSourceAddress).exchangeRate();
  39 |     |     }
  40 |     |     
  41 |     |     function getBalanceOfOwner(
  42 |     |         address yieldSourceAddress,
  43 |     |         address ownerOfShares
  44 |     |     ) external view returns (uint256) {
  45 |     |         return MockERC5115Tester(yieldSourceAddress).balanceOf(ownerOfShares);
  46 |     |     }
  47 |     |     
  48 |     |     function getTVLByOwnerOfShares(
  49 |     |         address yieldSourceAddress,
  50 |     |         address ownerOfShares
  51 |     |     ) external view returns (uint256) {
  52 |     |         uint256 shares = MockERC5115Tester(yieldSourceAddress).balanceOf(ownerOfShares);
  53 |     |         uint256 exchangeRate = MockERC5115Tester(yieldSourceAddress).exchangeRate();
  54 |     |         return (shares * exchangeRate) / 1e18;
  55 |     |     }
  56 |     |     
  57 |     |     function getTVL(address yieldSourceAddress) external view returns (uint256) {
  58 |     |         uint256 totalShares = MockERC5115Tester(yieldSourceAddress).totalSupply();
  59 |     |         uint256 exchangeRate = MockERC5115Tester(yieldSourceAddress).exchangeRate();
  60 |     |         return (totalShares * exchangeRate) / 1e18;
  61 |     |     }
  62 |     |     
  63 |     |     function getPricePerShareMultiple(
  64 |     |         address[] memory yieldSourceAddresses
  65 |     |     ) external view returns (uint256[] memory) {
  66 |     |         uint256[] memory prices = new uint256[](yieldSourceAddresses.length);
  67 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  68 |     |             prices[i] = MockERC5115Tester(yieldSourceAddresses[i]).exchangeRate();
  69 |     |         }
  70 |     |         return prices;
  71 |     |     }
  72 |     |     
  73 |     |     function getTVLByOwnerOfSharesMultiple(
  74 |     |         address[] memory yieldSourceAddresses,
  75 |     |         address[][] memory ownersOfShares
  76 |     |     ) external view returns (uint256[][] memory) {
  77 |     |         uint256[][] memory result = new uint256[][](yieldSourceAddresses.length);
  78 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  79 |     |             result[i] = new uint256[](ownersOfShares[i].length);
  80 |     |             uint256 exchangeRate = MockERC5115Tester(yieldSourceAddresses[i]).exchangeRate();
  81 |     |             for (uint256 j = 0; j < ownersOfShares[i].length; j++) {
  82 |     |                 uint256 shares = MockERC5115Tester(yieldSourceAddresses[i]).balanceOf(ownersOfShares[i][j]);
  83 |     |                 result[i][j] = (shares * exchangeRate) / 1e18;
  84 |     |             }
  85 |     |         }
  86 |     |         return result;
  87 |     |     }
  88 |     |     
  89 |     |     function getTVLMultiple(
  90 |     |         address[] memory yieldSourceAddresses
  91 |     |     ) external view returns (uint256[] memory) {
  92 |     |         uint256[] memory tvls = new uint256[](yieldSourceAddresses.length);
  93 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  94 |     |             uint256 totalShares = MockERC5115Tester(yieldSourceAddresses[i]).totalSupply();
  95 |     |             uint256 exchangeRate = MockERC5115Tester(yieldSourceAddresses[i]).exchangeRate();
  96 |     |             tvls[i] = (totalShares * exchangeRate) / 1e18;
  97 |     |         }
  98 |     |         return tvls;
  99 |     |     }
 100 |     |     
 101 |     |     function isValidUnderlyingAsset(address, address asset) external view returns (bool) {
 102 |     |         return validAssetMap[asset];
 103 |     |     }
 104 |     |     
 105 |     |     function isValidUnderlyingAssets(
 106 |     |         address[] memory,
 107 |     |         address[] memory assets
 108 |     |     ) external view returns (bool[] memory) {
 109 |     |         bool[] memory validities = new bool[](assets.length);
 110 |     |         for (uint256 i = 0; i < assets.length; i++) {
 111 |     |             validities[i] = validAssetMap[assets[i]];
 112 |     |         }
 113 |     |         return validities;
 114 |     |     }
 115 |     |     
 116 |     |     function getAssetOutputWithFees(
 117 |     |         bytes32,
 118 |     |         address yieldSourceAddress,
 119 |     |         address assetOut,
 120 |     |         address,
 121 |     |         uint256 sharesIn
 122 |     |     ) external view returns (uint256) {
 123 |     |         return MockERC5115Tester(yieldSourceAddress).previewRedeem(assetOut, sharesIn);
 124 |     |     }
 125 |     | }

/opt/scfuzzbench/work/target/test/recon/mocks/MockERC7540Tester.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {MockERC20} from "@recon/MockERC20.sol";
   5 |     | import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
   6 |     | 
   7 |     | abstract contract ERC7575 is MockERC20 {
   8 | *   |     MockERC20 public immutable asset;
   9 |     | 
  10 |     |     event Deposit(
  11 |     |         address indexed sender,
  12 |     |         address indexed owner,
  13 |     |         uint256 assets,
  14 |     |         uint256 shares
  15 |     |     );
  16 |     |     event Withdraw(
  17 |     |         address indexed sender,
  18 |     |         address indexed receiver,
  19 |     |         address indexed owner,
  20 |     |         uint256 assets,
  21 |     |         uint256 shares
  22 |     |     );
  23 |     | 
  24 | *   |     constructor(MockERC20 _asset) MockERC20("MockERC7540Tester", "M7540", 18) {
  25 | *   |         asset = _asset;
  26 |     |     }
  27 |     | 
  28 | *   |     function share() external view returns (address shareTokenAddress) {
  29 | *   |         return address(this);
  30 |     |     }
  31 |     | 
  32 | *   |     function totalAssets() public view virtual returns (uint256) {
  33 | *   |         return asset.balanceOf(address(this));
  34 |     |     }
  35 |     | 
  36 |     |     function convertToShares(
  37 |     |         uint256 assets
  38 |     |     ) public view virtual returns (uint256) {
  39 |     |         uint256 supply = totalSupply;
  40 |     |         return supply == 0 ? assets : (assets * supply) / totalAssets();
  41 |     |     }
  42 |     | 
  43 | *   |     function convertToAssets(
  44 |     |         uint256 shares
  45 | *   |     ) public view virtual returns (uint256) {
  46 | *   |         uint256 supply = totalSupply;
  47 | *   |         return supply == 0 ? shares : (shares * totalAssets()) / supply;
  48 |     |     }
  49 |     | 
  50 | *   |     function maxDeposit(address) public pure virtual returns (uint256) {
  51 | *   |         return type(uint256).max;
  52 |     |     }
  53 |     | 
  54 |     |     function maxMint(address) public pure virtual returns (uint256) {
  55 |     |         return type(uint256).max;
  56 |     |     }
  57 |     | 
  58 | *   |     function maxWithdraw(address owner) public view virtual returns (uint256) {
  59 | *   |         return convertToAssets(balanceOf[owner]);
  60 |     |     }
  61 |     | 
  62 | *   |     function maxRedeem(address owner) public view virtual returns (uint256) {
  63 | *   |         return balanceOf[owner];
  64 |     |     }
  65 |     | 
  66 | *   |     function previewDeposit(
  67 |     |         uint256 assets
  68 | *   |     ) public view virtual returns (uint256) {
  69 | *   |         return convertToShares(assets);
  70 |     |     }
  71 |     | 
  72 |     |     function previewMint(uint256 shares) public view virtual returns (uint256) {
  73 |     |         uint256 supply = totalSupply;
  74 |     |         return supply == 0 ? shares : (shares * totalAssets()) / supply;
  75 |     |     }
  76 |     | 
  77 | *   |     function previewWithdraw(
  78 |     |         uint256 assets
  79 | *   |     ) public view virtual returns (uint256) {
  80 | *   |         uint256 supply = totalSupply;
  81 | *   |         return supply == 0 ? assets : (assets * supply) / totalAssets();
  82 |     |     }
  83 |     | 
  84 | *   |     function previewRedeem(
  85 |     |         uint256 shares
  86 | *   |     ) public view virtual returns (uint256) {
  87 | *   |         return convertToAssets(shares);
  88 |     |     }
  89 |     | 
  90 | *   |     function deposit(
  91 |     |         uint256 assets,
  92 |     |         address receiver
  93 | *   |     ) public virtual returns (uint256 shares) {
  94 | *   |         shares = previewDeposit(assets);
  95 | *   |         asset.transferFrom(msg.sender, address(this), assets);
  96 | *   |         _mint(receiver, shares);
  97 | *   |         emit Deposit(msg.sender, receiver, assets, shares);
  98 |     |     }
  99 |     | 
 100 | *   |     function mint(
 101 |     |         uint256 shares,
 102 |     |         address receiver
 103 | *   |     ) public virtual returns (uint256 assets) {
 104 | *   |         assets = previewMint(shares);
 105 | *   |         asset.transferFrom(msg.sender, address(this), assets);
 106 | *   |         _mint(receiver, shares);
 107 | *   |         emit Deposit(msg.sender, receiver, assets, shares);
 108 |     |     }
 109 |     | }
 110 |     | 
 111 | *   | contract MockERC7540Tester is ERC7575, IERC165 {
 112 |     |     event DepositRequest(
 113 |     |         address indexed controller,
 114 |     |         address indexed owner,
 115 |     |         uint256 indexed requestId,
 116 |     |         address sender,
 117 |     |         uint256 assets
 118 |     |     );
 119 |     |     event RedeemRequest(
 120 |     |         address indexed controller,
 121 |     |         address indexed owner,
 122 |     |         uint256 indexed requestId,
 123 |     |         address sender,
 124 |     |         uint256 shares
 125 |     |     );
 126 |     |     event OperatorSet(
 127 |     |         address indexed controller,
 128 |     |         address indexed operator,
 129 |     |         bool approved
 130 |     |     );
 131 |     | 
 132 |     |     struct DepositRequestStruct {
 133 |     |         uint256 assets;
 134 |     |         address controller;
 135 |     |         address owner;
 136 |     |         bool fulfilled;
 137 |     |         bool canceled;
 138 |     |     }
 139 |     | 
 140 |     |     struct RedeemRequestStruct {
 141 |     |         uint256 shares;
 142 |     |         address controller;
 143 |     |         address owner;
 144 |     |         bool fulfilled;
 145 |     |         bool canceled;
 146 |     |     }
 147 |     | 
 148 | *   |     uint256 private _nextRequestId = 1;
 149 |     | 
 150 |     |     mapping(uint256 => DepositRequestStruct) public depositRequests;
 151 |     |     mapping(uint256 => RedeemRequestStruct) public redeemRequests;
 152 |     |     mapping(address => mapping(address => bool)) public operators;
 153 |     |     mapping(uint256 => bool) public pendingCancelDeposit;
 154 |     |     mapping(uint256 => bool) public pendingCancelRedeem;
 155 |     | 
 156 | *   |     uint256 public yieldMultiplier = 10000; // 100% in basis points
 157 | *   |     uint256 private constant MAX_BPS = 10000;
 158 |     |     uint256 public totalLosses;
 159 |     |     uint256 public totalGains;
 160 |     |     uint256 public lossOnWithdraw;
 161 |     | 
 162 | *   |     constructor(address _asset) ERC7575(MockERC20(_asset)) {}
 163 |     | 
 164 |     |     // Operator Management
 165 | *   |     function setOperator(
 166 |     |         address operator,
 167 |     |         bool approved
 168 | *   |     ) external returns (bool) {
 169 | *   |         operators[msg.sender][operator] = approved;
 170 | *   |         emit OperatorSet(msg.sender, operator, approved);
 171 |     |         return true;
 172 |     |     }
 173 |     | 
 174 |     |     function isOperator(
 175 |     |         address controller,
 176 |     |         address operator
 177 |     |     ) external view returns (bool) {
 178 |     |         return operators[controller][operator];
 179 |     |     }
 180 |     | 
 181 |     |     // Async Deposit Flow
 182 | *   |     function requestDeposit(
 183 |     |         uint256 assets,
 184 |     |         address controller,
 185 |     |         address owner
 186 | *   |     ) external returns (uint256 requestId) {
 187 | *   |         requestId = _nextRequestId++;
 188 | *   |         depositRequests[requestId] = DepositRequestStruct({
 189 | *   |             assets: assets,
 190 |     |             controller: controller,
 191 |     |             owner: owner,
 192 |     |             fulfilled: false,
 193 |     |             canceled: false
 194 |     |         });
 195 |     | 
 196 | *   |         asset.transferFrom(msg.sender, address(this), assets);
 197 | *   |         emit DepositRequest(controller, owner, requestId, msg.sender, assets);
 198 |     |     }
 199 |     | 
 200 |     |     function pendingDepositRequest(
 201 |     |         uint256 requestId,
 202 |     |         address controller
 203 |     |     ) external view returns (uint256) {
 204 |     |         DepositRequestStruct storage request = depositRequests[requestId];
 205 | *   |         if (
 206 | *   |             request.controller != controller ||
 207 |     |             request.fulfilled ||
 208 |     |             request.canceled
 209 |     |         ) {
 210 | *   |             return 0;
 211 |     |         }
 212 |     |         return request.assets;
 213 |     |     }
 214 |     | 
 215 |     |     function claimableDepositRequest(
 216 |     |         uint256 requestId,
 217 |     |         address controller
 218 |     |     ) external view returns (uint256) {
 219 |     |         DepositRequestStruct storage request = depositRequests[requestId];
 220 |     |         if (
 221 |     |             request.controller != controller ||
 222 |     |             request.fulfilled ||
 223 |     |             request.canceled
 224 |     |         ) {
 225 |     |             return 0;
 226 |     |         }
 227 |     |         return request.assets;
 228 |     |     }
 229 |     | 
 230 |     |     function pendingCancelDepositRequest(
 231 |     |         uint256 requestId,
 232 |     |         address controller
 233 |     |     ) external view returns (bool) {
 234 |     |         DepositRequestStruct storage request = depositRequests[requestId];
 235 |     |         return
 236 |     |             request.controller == controller && pendingCancelDeposit[requestId];
 237 |     |     }
 238 |     | 
 239 |     |     // Override deposit to handle async requests
 240 | *   |     function deposit(
 241 |     |         uint256 assets,
 242 |     |         address receiver,
 243 |     |         address controller
 244 | *   |     ) public returns (uint256 shares) {
 245 | *   |         require(
 246 | *   |             msg.sender == controller || operators[controller][msg.sender],
 247 |     |             "Not authorized"
 248 |     |         );
 249 |     | 
 250 |     |         // Find and fulfill a matching deposit request
 251 | *   |         for (uint256 i = 1; i < _nextRequestId; i++) {
 252 | *   |             DepositRequestStruct storage request = depositRequests[i];
 253 | *   |             if (
 254 | *   |                 request.controller == controller &&
 255 |     |                 !request.fulfilled &&
 256 |     |                 !request.canceled &&
 257 |     |                 request.assets >= assets
 258 |     |             ) {
 259 |     |                 shares = previewDeposit(assets);
 260 |     |                 request.fulfilled = true;
 261 |     |                 _mint(receiver, shares);
 262 |     | 
 263 |     |                 // Refund excess assets if any
 264 |     |                 if (request.assets > assets) {
 265 |     |                     asset.transfer(controller, request.assets - assets);
 266 |     |                 }
 267 |     | 
 268 |     |                 emit Deposit(msg.sender, receiver, assets, shares);
 269 |     |                 return shares;
 270 |     |             }
 271 |     |         }
 272 |     | 
 273 |     |         // Fallback to synchronous deposit if no matching request
 274 | *   |         return super.deposit(assets, receiver);
 275 |     |     }
 276 |     | 
 277 | *   |     function withdraw(
 278 |     |         uint256 assets,
 279 |     |         address receiver,
 280 |     |         address owner
 281 | *   |     ) public returns (uint256 shares) {
 282 | *   |         shares = previewWithdraw(assets);
 283 | *   |         if (msg.sender != owner) {
 284 | *   |             allowance[owner][msg.sender] -= shares;
 285 |     |         }
 286 | *   |         _burn(owner, shares);
 287 | *   |         uint256 lossyAssets = assets - ((assets * lossOnWithdraw) / MAX_BPS);
 288 |     | 
 289 | *   |         asset.transfer(receiver, lossyAssets);
 290 | *   |         emit Withdraw(msg.sender, receiver, owner, lossyAssets, shares);
 291 |     |     }
 292 |     | 
 293 | *   |     function redeem(
 294 |     |         uint256 shares,
 295 |     |         address receiver,
 296 |     |         address owner
 297 | *   |     ) public returns (uint256 assets) {
 298 | *   |         assets = previewRedeem(shares);
 299 | *   |         if (msg.sender != owner) {
 300 | *   |             allowance[owner][msg.sender] -= shares;
 301 |     |         }
 302 | *   |         _burn(owner, shares);
 303 | *   |         uint256 lossyAssets = assets - ((assets * lossOnWithdraw) / MAX_BPS);
 304 |     | 
 305 | *   |         asset.transfer(receiver, lossyAssets);
 306 | *   |         emit Withdraw(msg.sender, receiver, owner, lossyAssets, shares);
 307 |     |     }
 308 |     | 
 309 |     |     // Async Redeem Flow
 310 | *   |     function requestRedeem(
 311 |     |         uint256 shares,
 312 |     |         address controller,
 313 |     |         address owner
 314 | *   |     ) external returns (uint256 requestId) {
 315 | *   |         requestId = _nextRequestId++;
 316 | *   |         redeemRequests[requestId] = RedeemRequestStruct({
 317 |     |             shares: shares,
 318 |     |             controller: controller,
 319 |     |             owner: owner,
 320 |     |             fulfilled: false,
 321 |     |             canceled: false
 322 |     |         });
 323 |     | 
 324 | *   |         emit RedeemRequest(controller, owner, requestId, msg.sender, shares);
 325 |     |     }
 326 |     | 
 327 |     |     function pendingRedeemRequest(
 328 |     |         uint256 requestId,
 329 |     |         address controller
 330 |     |     ) external view returns (uint256) {
 331 |     |         RedeemRequestStruct storage request = redeemRequests[requestId];
 332 |     |         if (
 333 |     |             request.controller != controller ||
 334 |     |             request.fulfilled ||
 335 |     |             request.canceled
 336 |     |         ) {
 337 |     |             return 0;
 338 |     |         }
 339 |     |         return request.shares;
 340 |     |     }
 341 |     | 
 342 | *   |     function claimableRedeemRequest(
 343 |     |         uint256 requestId,
 344 |     |         address controller
 345 | *   |     ) external view returns (uint256) {
 346 | *   |         RedeemRequestStruct storage request = redeemRequests[requestId];
 347 |     |         if (
 348 | *   |             request.controller != controller ||
 349 |     |             request.fulfilled ||
 350 |     |             request.canceled
 351 |     |         ) {
 352 |     |             return 0;
 353 |     |         }
 354 |     |         return request.shares;
 355 |     |     }
 356 |     | 
 357 |     |     function pendingCancelRedeemRequest(
 358 |     |         uint256 requestId,
 359 |     |         address controller
 360 |     |     ) external view returns (bool) {
 361 |     |         RedeemRequestStruct storage request = redeemRequests[requestId];
 362 |     |         return
 363 |     |             request.controller == controller && pendingCancelRedeem[requestId];
 364 |     |     }
 365 |     | 
 366 |     |     // Cancel Operations
 367 | *   |     function cancelDepositRequest(
 368 |     |         uint256 requestId,
 369 |     |         address controller
 370 |     |     ) external {
 371 | *   |         require(
 372 | *   |             msg.sender == controller || operators[controller][msg.sender],
 373 |     |             "Not authorized"
 374 |     |         );
 375 | *   |         DepositRequestStruct storage request = depositRequests[requestId];
 376 | *   |         require(
 377 | *   |             request.controller == controller && !request.fulfilled,
 378 |     |             "Invalid request"
 379 |     |         );
 380 |     | 
 381 |     |         pendingCancelDeposit[requestId] = true;
 382 |     |     }
 383 |     | 
 384 | *   |     function claimCancelDepositRequest(
 385 |     |         uint256 requestId,
 386 |     |         address receiver,
 387 |     |         address controller
 388 | *   |     ) external returns (uint256 assets) {
 389 | *   |         DepositRequestStruct storage request = depositRequests[requestId];
 390 |     | 
 391 | *   |         assets = request.assets;
 392 | *   |         request.canceled = true;
 393 | *   |         pendingCancelDeposit[requestId] = false;
 394 |     | 
 395 | *   |         asset.transfer(receiver, assets);
 396 |     |     }
 397 |     | 
 398 | *   |     function cancelRedeemRequest(
 399 |     |         uint256 requestId,
 400 |     |         address controller
 401 |     |     ) external {
 402 | *   |         RedeemRequestStruct storage request = redeemRequests[requestId];
 403 |     | 
 404 | *   |         pendingCancelRedeem[requestId] = true;
 405 |     |     }
 406 |     | 
 407 | *   |     function claimCancelRedeemRequest(
 408 |     |         uint256 requestId,
 409 |     |         address receiver,
 410 |     |         address controller
 411 | *   |     ) external returns (uint256 shares) {
 412 | *   |         RedeemRequestStruct storage request = redeemRequests[requestId];
 413 |     | 
 414 | *   |         shares = request.shares;
 415 | *   |         request.canceled = true;
 416 | *   |         pendingCancelRedeem[requestId] = false;
 417 |     | 
 418 | *   |         _mint(receiver, shares);
 419 |     |     }
 420 |     | 
 421 |     |     // Placeholder functions for Centrifuge compatibility
 422 |     |     function poolId() external pure returns (uint64) {
 423 |     |         return 1;
 424 |     |     }
 425 |     | 
 426 |     |     function trancheId() external pure returns (bytes16) {
 427 |     |         return bytes16(uint128(1));
 428 |     |     }
 429 |     | 
 430 |     |     // Yield simulation functions (similar to MockERC4626Tester)
 431 |     |     // Primary way that 7540 vaults receive losses is on rounding in redemptions so we just simulate a loss that reduces total asset balance
 432 |     |     function increaseYield(uint256 increasePercentageFP4) external {
 433 |     |         uint256 amount = (totalAssets() * increasePercentageFP4) / MAX_BPS;
 434 |     |         MockERC20(asset).transferFrom(msg.sender, address(this), amount);
 435 |     |     }
 436 |     | 
 437 |     |     function decreaseYield(uint256 decreasePercentageFP4) external {
 438 |     |         uint256 amount = (totalAssets() * decreasePercentageFP4) / MAX_BPS;
 439 |     |         MockERC20(asset).transfer(address(0xbeef), amount);
 440 |     |     }
 441 |     | 
 442 | *   |     function simulateGain(uint256 gainAmount) external {
 443 | *   |         MockERC20(asset).transferFrom(msg.sender, address(this), gainAmount);
 444 | *   |         totalGains += gainAmount;
 445 |     |     }
 446 |     | 
 447 | *   |     function simulateLoss(uint256 lossAmount) external {
 448 | *   |         MockERC20(asset).transfer(address(0xbeef), lossAmount);
 449 | *   |         totalLosses += lossAmount;
 450 |     |     }
 451 |     | 
 452 |     |     /// @dev Set the loss on withdraw as percentage of the assets being withdrawn
 453 | *   |     function setLossOnWithdraw(uint256 _lossOnWithdraw) public {
 454 | *   |         _lossOnWithdraw %= MAX_BPS + 1; // clamp to ensure we set a max of 100%
 455 | *   |         lossOnWithdraw = _lossOnWithdraw;
 456 |     |     }
 457 |     | 
 458 |     |     /// @notice ERC165 interface detection
 459 | *   |     function supportsInterface(
 460 |     |         bytes4 interfaceId
 461 |     |     ) external pure override returns (bool) {
 462 |     |         return interfaceId == type(IERC165).interfaceId;
 463 |     |     }
 464 |     | }
 465 |     | 

/opt/scfuzzbench/work/target/test/recon/mocks/MockERC7540YieldSourceOracle.sol
   1 |     | // SPDX-License-Identifier: MIT
   2 |     | pragma solidity ^0.8.30;
   3 |     | 
   4 |     | import {IERC20Metadata} from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";
   5 |     | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   6 |     | import {IYieldSourceOracle} from "@superform-v2-core/src/interfaces/accounting/IYieldSourceOracle.sol";
   7 |     | import {MockERC7540Tester} from "./MockERC7540Tester.sol";
   8 |     | 
   9 |     | /// @title MockERC7540YieldSourceOracle
  10 |     | /// @notice Mock oracle for ERC7540 (Asynchronous Tokenized Vaults) in testing
  11 | *   | contract MockERC7540YieldSourceOracle is IYieldSourceOracle {
  12 |     |     mapping(address => bool) public validAssetMap;
  13 |     |     
  14 | *   |     function setValidAsset(address asset, bool isValid) external {
  15 | *   |         validAssetMap[asset] = isValid;
  16 |     |     }
  17 |     |     
  18 |     |     function decimals(address yieldSourceAddress) external view returns (uint8) {
  19 |     |         address share = MockERC7540Tester(yieldSourceAddress).share();
  20 |     |         return IERC20Metadata(share).decimals();
  21 |     |     }
  22 |     |     
  23 | *   |     function getShareOutput(
  24 |     |         address yieldSourceAddress,
  25 |     |         address,
  26 |     |         uint256 assetsIn
  27 | *   |     ) external view returns (uint256) {
  28 | *   |         return MockERC7540Tester(yieldSourceAddress).convertToShares(assetsIn);
  29 |     |     }
  30 |     |     
  31 |     |     function getAssetOutput(
  32 |     |         address yieldSourceAddress,
  33 |     |         address,
  34 |     |         uint256 sharesIn
  35 |     |     ) public view returns (uint256) {
  36 |     |         return MockERC7540Tester(yieldSourceAddress).convertToAssets(sharesIn);
  37 |     |     }
  38 |     |     
  39 |     |     function getPricePerShare(address yieldSourceAddress) external view returns (uint256) {
  40 |     |         address share = MockERC7540Tester(yieldSourceAddress).share();
  41 |     |         uint256 _decimals = IERC20Metadata(share).decimals();
  42 |     |         return MockERC7540Tester(yieldSourceAddress).convertToAssets(10 ** _decimals);
  43 |     |     }
  44 |     |     
  45 |     |     function getBalanceOfOwner(
  46 |     |         address yieldSourceAddress,
  47 |     |         address ownerOfShares
  48 |     |     ) external view returns (uint256) {
  49 |     |         return IERC20(MockERC7540Tester(yieldSourceAddress).share()).balanceOf(ownerOfShares);
  50 |     |     }
  51 |     |     
  52 |     |     function getTVLByOwnerOfShares(
  53 |     |         address yieldSourceAddress,
  54 |     |         address ownerOfShares
  55 |     |     ) external view returns (uint256) {
  56 |     |         address share = MockERC7540Tester(yieldSourceAddress).share();
  57 |     |         uint256 shares = IERC20(share).balanceOf(ownerOfShares);
  58 |     |         return MockERC7540Tester(yieldSourceAddress).convertToAssets(shares);
  59 |     |     }
  60 |     |     
  61 |     |     function getTVL(address yieldSourceAddress) external view returns (uint256) {
  62 |     |         return MockERC7540Tester(yieldSourceAddress).totalAssets();
  63 |     |     }
  64 |     |     
  65 |     |     function getPricePerShareMultiple(
  66 |     |         address[] memory yieldSourceAddresses
  67 |     |     ) external view returns (uint256[] memory) {
  68 |     |         uint256[] memory prices = new uint256[](yieldSourceAddresses.length);
  69 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  70 |     |             address share = MockERC7540Tester(yieldSourceAddresses[i]).share();
  71 |     |             uint256 _decimals = IERC20Metadata(share).decimals();
  72 |     |             prices[i] = MockERC7540Tester(yieldSourceAddresses[i]).convertToAssets(10 ** _decimals);
  73 |     |         }
  74 |     |         return prices;
  75 |     |     }
  76 |     |     
  77 |     |     function getTVLByOwnerOfSharesMultiple(
  78 |     |         address[] memory yieldSourceAddresses,
  79 |     |         address[][] memory ownersOfShares
  80 |     |     ) external view returns (uint256[][] memory) {
  81 |     |         uint256[][] memory result = new uint256[][](yieldSourceAddresses.length);
  82 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  83 |     |             result[i] = new uint256[](ownersOfShares[i].length);
  84 |     |             address share = MockERC7540Tester(yieldSourceAddresses[i]).share();
  85 |     |             for (uint256 j = 0; j < ownersOfShares[i].length; j++) {
  86 |     |                 uint256 shares = IERC20(share).balanceOf(ownersOfShares[i][j]);
  87 |     |                 result[i][j] = MockERC7540Tester(yieldSourceAddresses[i]).convertToAssets(shares);
  88 |     |             }
  89 |     |         }
  90 |     |         return result;
  91 |     |     }
  92 |     |     
  93 |     |     function getTVLMultiple(
  94 |     |         address[] memory yieldSourceAddresses
  95 |     |     ) external view returns (uint256[] memory) {
  96 |     |         uint256[] memory tvls = new uint256[](yieldSourceAddresses.length);
  97 |     |         for (uint256 i = 0; i < yieldSourceAddresses.length; i++) {
  98 |     |             tvls[i] = MockERC7540Tester(yieldSourceAddresses[i]).totalAssets();
  99 |     |         }
 100 |     |         return tvls;
 101 |     |     }
 102 |     |     
 103 |     |     function isValidUnderlyingAsset(address, address asset) external view returns (bool) {
 104 |     |         return validAssetMap[asset];
 105 |     |     }
 106 |     |     
 107 |     |     function isValidUnderlyingAssets(
 108 |     |         address[] memory,
 109 |     |         address[] memory assets
 110 |     |     ) external view returns (bool[] memory) {
 111 |     |         bool[] memory validities = new bool[](assets.length);
 112 |     |         for (uint256 i = 0; i < assets.length; i++) {
 113 |     |             validities[i] = validAssetMap[assets[i]];
 114 |     |         }
 115 |     |         return validities;
 116 |     |     }
 117 |     |     
 118 |     |     function getAssetOutputWithFees(
 119 |     |         bytes32,
 120 |     |         address yieldSourceAddress,
 121 |     |         address,
 122 |     |         address,
 123 |     |         uint256 sharesIn
 124 |     |     ) external view returns (uint256) {
 125 |     |         return MockERC7540Tester(yieldSourceAddress).convertToAssets(sharesIn);
 126 |     |     }
 127 |     | }

/opt/scfuzzbench/work/target/test/recon/targets/AdminTargets.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | // External dependencies
   5 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
   6 |     | import {vm} from "@chimera/Hevm.sol";
   7 |     | import {Panic} from "@recon/Panic.sol";
   8 |     | import {MockERC20} from "@recon/MockERC20.sol";
   9 |     | 
  10 |     | // System dependencies
  11 |     | import {ISuperVaultStrategy} from "src/interfaces/SuperVault/ISuperVaultStrategy.sol";
  12 |     | import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
  13 |     | 
  14 |     | // Test dependencies
  15 |     | import {YieldSourceType} from "test/recon/managers/YieldManager.sol";
  16 |     | import {BeforeAfter, OpType} from "../BeforeAfter.sol";
  17 |     | import {Properties} from "../Properties.sol";
  18 |     | 
  19 |     | abstract contract AdminTargets is BaseTargetFunctions, Properties {
  20 |     |     enum HookType {
  21 |     |         // ERC4626 Hooks
  22 |     |         ApproveAndDeposit4626,
  23 |     |         Deposit4626,
  24 |     |         Redeem4626,
  25 |     |         // ERC5115 Hooks
  26 |     |         ApproveAndDeposit5115,
  27 |     |         Deposit5115,
  28 |     |         Redeem5115,
  29 |     |         // ERC7540 Hooks
  30 |     |         Deposit7540,
  31 |     |         Redeem7540,
  32 |     |         RequestDeposit7540,
  33 |     |         RequestRedeem7540,
  34 |     |         ApproveAndRequestDeposit7540,
  35 |     |         CancelDepositRequest7540,
  36 |     |         CancelRedeemRequest7540,
  37 |     |         ClaimCancelDepositRequest7540,
  38 |     |         ClaimCancelRedeemRequest7540,
  39 |     |         Withdraw7540,
  40 |     |         // Super Vault Hooks
  41 |     |         CancelRedeem,
  42 |     |         SuperVaultWithdraw7540
  43 |     |     }
  44 |     | 
  45 |     |     /// CUSTOM TARGET FUNCTIONS - Add your own target functions here ///
  46 | *   |     function superVaultStrategy_executeHooks_clamped(
  47 |     |         uint256[] memory hookTypeInts,
  48 |     |         uint256[] memory amountsToInvest,
  49 |     |         bool[] memory usePrevHookAmounts
  50 |     |     ) public payable {
  51 |     |         // Limit the number of hooks to 10 maximum
  52 | *   |         uint256 numHooks = hookTypeInts.length;
  53 | *   |         if (numHooks > 10) {
  54 | *   |             numHooks = 10;
  55 |     |         }
  56 |     | 
  57 |     |         // Ensure all arrays have the same length
  58 | *   |         if (amountsToInvest.length < numHooks) {
  59 | *   |             numHooks = amountsToInvest.length;
  60 |     |         }
  61 | *   |         if (usePrevHookAmounts.length < numHooks) {
  62 | *   |             numHooks = usePrevHookAmounts.length;
  63 |     |         }
  64 |     | 
  65 |     |         // Return early if no hooks to execute
  66 | *   |         if (numHooks == 0) {
  67 | *   |             return;
  68 |     |         }
  69 |     | 
  70 |     |         // Create ExecuteArgs for the hooks
  71 | *   |         ISuperVaultStrategy.ExecuteArgs memory executeArgs = ISuperVaultStrategy
  72 |     |             .ExecuteArgs({
  73 | *   |                 hooks: new address[](numHooks),
  74 | *   |                 hookCalldata: new bytes[](numHooks),
  75 | *   |                 expectedAssetsOrSharesOut: new uint256[](numHooks),
  76 | *   |                 globalProofs: new bytes32[][](numHooks),
  77 | *   |                 strategyProofs: new bytes32[][](numHooks)
  78 |     |             });
  79 |     | 
  80 |     |         // Process each hook
  81 | *   |         uint256 totalAmountToDeposit;
  82 | *   |         for (uint256 i = 0; i < numHooks; i++) {
  83 |     |             // Convert integer to enum (will wrap around if > max enum value)
  84 | *   |             HookType hookType = HookType(hookTypeInts[i] % 17); // 17 is the total number of hooks
  85 |     | 
  86 |     |             // Clamp to the strategy's asset balance (not SuperVault's balance)
  87 | *   |             uint256 clampedAmount = amountsToInvest[i] %
  88 | *   |                 (MockERC20(superVault.asset()).balanceOf(
  89 | *   |                     address(superVaultStrategy)
  90 | *   |                 ) + 1);
  91 |     | 
  92 |     |             // Get the hook address and calldata
  93 | *   |             (
  94 | *   |                 address hookAddress,
  95 | *   |                 bytes memory hookCalldata
  96 | *   |             ) = _getHookAddressAndCalldata(
  97 | *   |                     hookType,
  98 | *   |                     clampedAmount,
  99 | *   |                     usePrevHookAmounts[i]
 100 |     |                 );
 101 |     | 
 102 | *   |             executeArgs.hooks[i] = hookAddress;
 103 | *   |             executeArgs.hookCalldata[i] = hookCalldata;
 104 | *   |             executeArgs.expectedAssetsOrSharesOut[i] = clampedAmount;
 105 | *   |             executeArgs.globalProofs[i] = new bytes32[](1);
 106 | *   |             executeArgs.strategyProofs[i] = new bytes32[](1);
 107 |     | 
 108 | *   |             totalAmountToDeposit += clampedAmount;
 109 |     |         }
 110 |     | 
 111 |     |         // Check that amount to be invested is less than the claimable assets so that it doesn't reinvest and prevent users from claiming
 112 | *   |         if (_claimableMoreThanInvested(totalAmountToDeposit)) return;
 113 |     | 
 114 |     |         // Execute all hooks
 115 | *r  |         this.superVaultStrategy_executeHooks{value: msg.value}(executeArgs);
 116 |     |     }
 117 |     | 
 118 | *   |     function _getHookAddressAndCalldata(
 119 |     |         HookType hookType,
 120 |     |         uint256 amountToInvest,
 121 |     |         bool usePrevHookAmount
 122 | *   |     ) internal view returns (address hookAddress, bytes memory hookCalldata) {
 123 | *   |         if (hookType == HookType.ApproveAndDeposit4626) {
 124 | *   |             hookAddress = address(approveAndDeposit4626Hook);
 125 | *   |             hookCalldata = abi.encodePacked(
 126 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 127 | *   |                 _getYieldSource(), // Address of the yield source
 128 | *   |                 superVault.asset(), // Address of the token to approve and deposit
 129 | *   |                 amountToInvest, // Amount to deposit
 130 | *   |                 usePrevHookAmount
 131 |     |             );
 132 | *   |         } else if (hookType == HookType.Deposit4626) {
 133 | *   |             hookAddress = address(deposit4626Hook);
 134 | *   |             hookCalldata = abi.encodePacked(
 135 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 136 | *   |                 _getYieldSource(), // Address of the yield source
 137 | *   |                 amountToInvest, // Amount to deposit
 138 | *   |                 usePrevHookAmount
 139 |     |             );
 140 | *   |         } else if (hookType == HookType.Redeem4626) {
 141 | *   |             hookAddress = address(redeem4626Hook);
 142 | *   |             hookCalldata = abi.encodePacked(
 143 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 144 | *   |                 _getYieldSource(), // Address of the yield source
 145 |     |                 amountToInvest, // Amount to redeem
 146 | *   |                 address(superVaultStrategy), // Receiver
 147 |     |                 address(superVaultStrategy) // Owner
 148 |     |             );
 149 | *   |         } else if (hookType == HookType.ApproveAndDeposit5115) {
 150 | *   |             hookAddress = address(approveAndDeposit5115Hook);
 151 | *   |             hookCalldata = abi.encodePacked(
 152 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 153 | *   |                 _getYieldSource(), // Address of the yield source
 154 | *   |                 superVault.asset(), // Address of the token to approve and deposit
 155 | *   |                 bytes32(0), // tokenId (for ERC5115)
 156 |     |                 amountToInvest, // Amount to deposit
 157 |     |                 usePrevHookAmount
 158 |     |             );
 159 | *   |         } else if (hookType == HookType.Deposit5115) {
 160 | *   |             hookAddress = address(deposit5115Hook);
 161 | *   |             hookCalldata = abi.encodePacked(
 162 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 163 | *   |                 _getYieldSource(), // Address of the yield source
 164 |     |                 bytes32(0), // tokenId (for ERC5115)
 165 |     |                 amountToInvest, // Amount to deposit
 166 |     |                 usePrevHookAmount
 167 |     |             );
 168 | *   |         } else if (hookType == HookType.Redeem5115) {
 169 | *   |             hookAddress = address(redeem5115Hook);
 170 | *   |             hookCalldata = abi.encodePacked(
 171 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 172 | *   |                 _getYieldSource(), // Address of the yield source
 173 | *   |                 bytes32(0), // tokenId (for ERC5115)
 174 |     |                 amountToInvest, // Amount to redeem
 175 | *   |                 address(superVaultStrategy), // Receiver
 176 |     |                 address(superVaultStrategy) // Owner
 177 |     |             );
 178 | *   |         } else if (hookType == HookType.Deposit7540) {
 179 | *   |             hookAddress = address(deposit7540Hook);
 180 |     |             hookCalldata = abi.encodePacked(
 181 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 182 | *   |                 _getYieldSource(), // Address of the yield source
 183 |     |                 amountToInvest, // Amount to deposit
 184 |     |                 address(superVaultStrategy), // Receiver
 185 |     |                 address(superVaultStrategy) // Controller
 186 |     |             );
 187 | *   |         } else if (hookType == HookType.Redeem7540) {
 188 | *   |             hookAddress = address(redeem7540Hook);
 189 | *   |             hookCalldata = abi.encodePacked(
 190 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 191 | *   |                 _getYieldSource(), // Address of the yield source
 192 | *   |                 amountToInvest, // Amount to redeem
 193 | *   |                 address(superVaultStrategy), // Receiver
 194 |     |                 address(superVaultStrategy), // Owner
 195 |     |                 address(superVaultStrategy) // Controller
 196 |     |             );
 197 | *   |         } else if (hookType == HookType.RequestDeposit7540) {
 198 | *   |             hookAddress = address(requestDeposit7540Hook);
 199 |     |             hookCalldata = abi.encodePacked(
 200 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 201 | *   |                 _getYieldSource(), // Address of the yield source
 202 |     |                 amountToInvest, // Amount to request deposit
 203 |     |                 address(superVaultStrategy), // Owner
 204 |     |                 address(superVaultStrategy) // Controller
 205 |     |             );
 206 | *   |         } else if (hookType == HookType.RequestRedeem7540) {
 207 | *   |             hookAddress = address(requestRedeem7540Hook);
 208 |     |             hookCalldata = abi.encodePacked(
 209 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 210 | *   |                 _getYieldSource(), // Address of the yield source
 211 |     |                 amountToInvest, // Amount to request redeem
 212 |     |                 address(superVaultStrategy), // Owner
 213 |     |                 address(superVaultStrategy) // Controller
 214 |     |             );
 215 | *   |         } else if (hookType == HookType.ApproveAndRequestDeposit7540) {
 216 | *   |             hookAddress = address(approveAndRequestDeposit7540Hook);
 217 | *   |             hookCalldata = abi.encodePacked(
 218 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 219 | *   |                 _getYieldSource(), // Address of the yield source
 220 | *   |                 superVault.asset(), // Address of the token to approve
 221 |     |                 amountToInvest, // Amount to request deposit
 222 | *   |                 address(superVaultStrategy), // Owner
 223 |     |                 address(superVaultStrategy) // Controller
 224 |     |             );
 225 | *   |         } else if (hookType == HookType.CancelDepositRequest7540) {
 226 | *   |             hookAddress = address(cancelDepositRequest7540Hook);
 227 | *   |             hookCalldata = abi.encodePacked(
 228 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 229 | *   |                 _getYieldSource(), // Address of the yield source
 230 | *   |                 address(superVaultStrategy) // Controller
 231 |     |             );
 232 | *   |         } else if (hookType == HookType.CancelRedeemRequest7540) {
 233 | *   |             hookAddress = address(cancelRedeemRequest7540Hook);
 234 |     |             hookCalldata = abi.encodePacked(
 235 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 236 | *   |                 _getYieldSource(), // Address of the yield source
 237 |     |                 address(superVaultStrategy) // Controller
 238 |     |             );
 239 | *   |         } else if (hookType == HookType.ClaimCancelDepositRequest7540) {
 240 | *   |             hookAddress = address(claimCancelDepositRequest7540Hook);
 241 | *   |             hookCalldata = abi.encodePacked(
 242 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 243 | *   |                 _getYieldSource(), // Address of the yield source
 244 | *   |                 address(superVaultStrategy), // Receiver
 245 |     |                 address(superVaultStrategy) // Controller
 246 |     |             );
 247 | *   |         } else if (hookType == HookType.ClaimCancelRedeemRequest7540) {
 248 | *   |             hookAddress = address(claimCancelRedeemRequest7540Hook);
 249 |     |             hookCalldata = abi.encodePacked(
 250 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 251 | *   |                 _getYieldSource(), // Address of the yield source
 252 |     |                 address(superVaultStrategy), // Receiver
 253 |     |                 address(superVaultStrategy) // Controller
 254 |     |             );
 255 | *   |         } else if (hookType == HookType.Withdraw7540) {
 256 | *   |             hookAddress = address(withdraw7540Hook);
 257 |     |             hookCalldata = abi.encodePacked(
 258 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 259 | *   |                 _getYieldSource(), // Address of the yield source
 260 |     |                 amountToInvest, // Amount to withdraw
 261 |     |                 address(superVaultStrategy), // Receiver
 262 |     |                 address(superVaultStrategy), // Owner
 263 |     |                 address(superVaultStrategy) // Controller
 264 |     |             );
 265 | *   |         } else if (hookType == HookType.CancelRedeem) {
 266 | *   |             hookAddress = address(cancelRedeemHook);
 267 |     |             hookCalldata = abi.encodePacked(
 268 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 269 | *   |                 _getYieldSource(), // Address of the yield source
 270 |     |                 address(superVaultStrategy) // Controller
 271 |     |             );
 272 | *   |         } else if (hookType == HookType.SuperVaultWithdraw7540) {
 273 |     |             hookAddress = address(superVaultWithdraw7540Hook);
 274 |     |             hookCalldata = abi.encodePacked(
 275 |     |                 bytes32(0), // yieldSourceOracleId placeholder
 276 |     |                 _getYieldSource(), // Address of the yield source
 277 |     |                 amountToInvest, // Amount to withdraw
 278 |     |                 address(superVaultStrategy), // Receiver
 279 |     |                 address(superVaultStrategy), // Owner
 280 |     |                 address(superVaultStrategy) // Controller
 281 |     |             );
 282 |     |         }
 283 |     |     }
 284 |     | 
 285 | *r  |     function superVaultStrategy_fulfillRedeemRequests_clamped(
 286 |     |         uint256 redeemAmount
 287 | *   |     ) public {
 288 |     |         // Find a controller that has pending redeem requests
 289 | *   |         address selectedController = _getActor();
 290 | *   |         uint256 pendingAmount = superVaultStrategy.pendingRedeemRequest(
 291 |     |             selectedController
 292 |     |         );
 293 |     | 
 294 |     |         // Clamp using the actor's pending amount
 295 | *   |         uint256 actualRedeemAmount = redeemAmount % (pendingAmount + 1);
 296 |     | 
 297 | *   |         address[] memory controllers = new address[](1);
 298 | *   |         controllers[0] = selectedController;
 299 |     | 
 300 |     |         // Determine yield source type from currently active yield source
 301 | *   |         YieldSourceType activeYieldSourceType = _getYieldSourceTypeFromAddress(
 302 | *   |             _getYieldSource()
 303 |     |         );
 304 | *   |         address redeemHook = _getRedeemHookForType(activeYieldSourceType);
 305 |     | 
 306 |     |         // Create realistic hook calldata for redeem operation
 307 | *   |         bytes memory redeemHookCalldata;
 308 |     | 
 309 | *   |         if (
 310 | *   |             activeYieldSourceType == YieldSourceType.ERC4626 ||
 311 | *   |             activeYieldSourceType == YieldSourceType.ERC5115
 312 |     |         ) {
 313 |     |             // ERC4626/ERC5115 Layout: bytes32 oracleId, address yieldSource, address owner, uint256 shares, bool usePrevAmount
 314 | *   |             redeemHookCalldata = abi.encodePacked(
 315 | *   |                 bytes32(0), // yieldSourceOracleId placeholder
 316 | *   |                 _getYieldSource(), // Current active yield source
 317 | *   |                 address(superVaultStrategy), // Owner (strategy owns the yield source shares)
 318 | *   |                 actualRedeemAmount, // Amount to redeem (matches controller's pending request)
 319 |     |                 false // Don't use previous hook amount
 320 |     |             );
 321 |     |         } else {
 322 |     |             // ERC7540 Layout: bytes32 oracleId, address yieldSource, uint256 shares, bool usePrevAmount
 323 | *   |             redeemHookCalldata = abi.encodePacked(
 324 | *   |                 bytes32(0), // yieldSourceOracleId placeholder
 325 | *   |                 _getYieldSource(), // Current active yield source
 326 | *   |                 actualRedeemAmount, // Amount to redeem (matches controller's pending request)
 327 | *   |                 false // Don't use previous hook amount
 328 |     |             );
 329 |     |         }
 330 |     | 
 331 |     |         // Create arrays for FulfillArgs
 332 | *   |         address[] memory hooks = new address[](1);
 333 | *   |         hooks[0] = redeemHook;
 334 |     | 
 335 | *   |         bytes[] memory hookCalldata = new bytes[](1);
 336 | *   |         hookCalldata[0] = redeemHookCalldata;
 337 |     | 
 338 | *   |         uint256[] memory expectedAssetsOrSharesOut = new uint256[](1);
 339 | *   |         expectedAssetsOrSharesOut[0] = 1; // @audit Allow max losse amount matching the actual redeem
 340 |     | 
 341 | *   |         bytes32[][] memory globalProofs = new bytes32[][](1);
 342 | *   |         globalProofs[0] = new bytes32[](0); // Empty proof for UnsafeSuperVaultAggregator
 343 |     | 
 344 | *   |         bytes32[][] memory strategyProofs = new bytes32[][](1);
 345 | *   |         strategyProofs[0] = new bytes32[](0); // Empty proof
 346 |     | 
 347 |     |         // Create the FulfillArgs struct
 348 | *   |         ISuperVaultStrategy.FulfillArgs memory fulfillArgs = ISuperVaultStrategy
 349 |     |             .FulfillArgs({
 350 | *   |                 controllers: controllers,
 351 | *   |                 hooks: hooks,
 352 | *   |                 hookCalldata: hookCalldata,
 353 | *   |                 expectedAssetsOrSharesOut: expectedAssetsOrSharesOut,
 354 | *   |                 globalProofs: globalProofs,
 355 | *   |                 strategyProofs: strategyProofs
 356 |     |             });
 357 |     | 
 358 |     |         // Execute the function
 359 | *   |         superVaultStrategy_fulfillRedeemRequests_ASSERTION_STRATEGY_NO_LOSS_ON_FULFILLMENT(fulfillArgs);
 360 |     |     }
 361 |     | 
 362 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
 363 |     | 
 364 | *   |     function superVaultStrategy_executeHooks(
 365 |     |         ISuperVaultStrategy.ExecuteArgs memory args
 366 |     |     ) public payable asAdmin {
 367 | *r  |         superVaultStrategy.executeHooks{value: msg.value}(args);
 368 |     | 
 369 |     |         executeHooksSuccess = true;
 370 |     |     }
 371 |     | 
 372 |     |     /// @dev Property: superVaultStrategy does not incur loss on fulfillment
 373 | *r  |     function superVaultStrategy_fulfillRedeemRequests_ASSERTION_STRATEGY_NO_LOSS_ON_FULFILLMENT(
 374 |     |         ISuperVaultStrategy.FulfillArgs memory args
 375 | *   |     ) public updateGhostsWithOpType(OpType.FULFILL) {
 376 | *   |         uint256 summedExpectedAssets;
 377 | *   |         for (uint256 i; i < args.expectedAssetsOrSharesOut.length; i++) {
 378 | *   |             summedExpectedAssets += args.expectedAssetsOrSharesOut[i];
 379 |     |         }
 380 |     | 
 381 |     |         // no need to prank because called as admin address(this)
 382 | *r  |         superVaultStrategy.fulfillRedeemRequests(args);
 383 |     | 
 384 | *   |         uint256 assetBalanceAfter = MockERC20(superVault.asset()).balanceOf(
 385 | *   |             address(superVaultStrategy)
 386 |     |         );
 387 |     | 
 388 | *   |         gte(
 389 | *   |             assetBalanceAfter,
 390 | *   |             summedExpectedAssets,
 391 | *   |             ASSERTION_STRATEGY_NO_LOSS_ON_FULFILLMENT
 392 |     |         );
 393 |     |     }
 394 |     | 
 395 |     |     // Functions that require SuperGovernor access
 396 |     |     /// @dev removed because we're bypassing hook validation
 397 |     |     // function superVaultAggregator_setHooksRootUpdateTimelock(
 398 |     |     //     uint256 newTimelock
 399 |     |     // ) public asAdmin {
 400 |     |     //     superVaultAggregator.setHooksRootUpdateTimelock(newTimelock);
 401 |     |     // }
 402 |     | 
 403 |     |     /// @dev removed because we're bypassing hook validation
 404 |     |     // function superVaultAggregator_proposeGlobalHooksRoot(
 405 |     |     //     bytes32 newRoot
 406 |     |     // ) public asAdmin {
 407 |     |     //     superVaultAggregator.proposeGlobalHooksRoot(newRoot);
 408 |     |     // }
 409 |     | 
 410 |     |     /// @dev removed because we're bypassing hook validation
 411 |     |     // function superVaultAggregator_executeGlobalHooksRootUpdate()
 412 |     |     //     public
 413 |     |     //     asAdmin
 414 |     |     // {
 415 |     |     //     superVaultAggregator.executeGlobalHooksRootUpdate();
 416 |     |     // }
 417 |     | 
 418 |     |     /// @dev removed because we're bypassing hook validation
 419 |     |     // function superVaultAggregator_setGlobalHooksRootVetoStatus(
 420 |     |     //     bool vetoed
 421 |     |     // ) public asAdmin {
 422 |     |     //     superVaultAggregator.setGlobalHooksRootVetoStatus(vetoed);
 423 |     |     // }
 424 |     | 
 425 |     |     /// @dev removed because we're bypassing hook validation
 426 |     |     // function superVaultAggregator_setStrategyHooksRootVetoStatus(
 427 |     |     //     address strategy,
 428 |     |     //     bool vetoed
 429 |     |     // ) public asAdmin {
 430 |     |     //     superVaultAggregator.setStrategyHooksRootVetoStatus(strategy, vetoed);
 431 |     |     // }
 432 |     | 
 433 | *r  |     function superVaultAggregator_changePrimaryManager(
 434 |     |         address strategy,
 435 |     |         address newManager
 436 |     |     ) public asAdmin {
 437 | *   |         superVaultAggregator.changePrimaryManager(strategy, newManager);
 438 |     |     }
 439 |     | 
 440 |     |     /// @dev won't achieve coverage until issue outlined here is resolved: https://github.com/Recon-Fuzz/superform-review/issues/5
 441 | *r  |     function superVaultAggregator_slashStake(
 442 |     |         address manager,
 443 |     |         uint256 amount
 444 |     |     ) public asAdmin {
 445 | *   |         superVaultAggregator.slashStake(manager, amount);
 446 |     |     }
 447 |     | 
 448 |     |     /// Helpers
 449 |     | 
 450 |     |     function _requestedSharesForControllers(
 451 |     |         address[] memory controllers
 452 |     |     ) internal returns (uint256) {
 453 |     |         uint256 totalRequested;
 454 |     |         for (uint256 i; i < controllers.length; i++) {
 455 |     |             totalRequested += superVault.pendingRedeemRequest(
 456 |     |                 0,
 457 |     |                 controllers[i]
 458 |     |             );
 459 |     |         }
 460 |     | 
 461 |     |         return totalRequested;
 462 |     |     }
 463 |     | 
 464 |     |     function _sumSuperVaultValsForControllers(
 465 |     |         address[] memory controllers
 466 |     |     )
 467 |     |         internal
 468 |     |         view
 469 |     |         returns (uint256 sumAccumulatorShares, uint256 sumAccumulatorCostBasis)
 470 |     |     {
 471 |     |         for (uint256 i; i < controllers.length; i++) {
 472 |     |             sumAccumulatorShares += superVaultStrategy
 473 |     |                 .getSuperVaultState(controllers[i])
 474 |     |                 .accumulatorShares;
 475 |     |             sumAccumulatorCostBasis += superVaultStrategy
 476 |     |                 .getSuperVaultState(controllers[i])
 477 |     |                 .accumulatorCostBasis;
 478 |     |         }
 479 |     |     }
 480 |     | 
 481 | *   |     function _claimableMoreThanInvested(
 482 |     |         uint256 totalAmountToDeposit
 483 | *   |     ) internal returns (bool) {
 484 | *   |         address[] memory actors = _getActors();
 485 | *   |         uint256 totalClaimable;
 486 | *   |         for (uint256 i; i < actors.length; i++) {
 487 | *   |             uint256 claimableRedemptions = superVault.claimableRedeemRequest(
 488 |     |                 0,
 489 | *   |                 actors[i]
 490 |     |             );
 491 | *   |             uint256 claimableRedemptionsAsAssets = superVault.convertToAssets(
 492 |     |                 claimableRedemptions
 493 |     |             );
 494 | *   |             totalClaimable += claimableRedemptionsAsAssets;
 495 |     |         }
 496 |     | 
 497 | *   |         uint256 currentStrategyBalance = MockERC20(superVault.asset())
 498 | *   |             .balanceOf(address(superVaultStrategy));
 499 |     | 
 500 |     |         // Don't allow investing more than the claimable amount
 501 | *   |         if (totalAmountToDeposit > totalClaimable) {
 502 | *   |             return true;
 503 |     |         }
 504 |     | 
 505 |     |         // Ensure strategy has sufficient assets remaining after investment to cover claimable amounts
 506 | *   |         uint256 remainingStrategyBalance = currentStrategyBalance -
 507 | *   |             totalAmountToDeposit;
 508 | *   |         if (remainingStrategyBalance < totalClaimable) {
 509 | *   |             return true;
 510 |     |         }
 511 |     | 
 512 | *   |         return false;
 513 |     |     }
 514 |     | }
 515 |     | 

/opt/scfuzzbench/work/target/test/recon/targets/DoomsdayTargets.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
   5 |     | import {vm} from "@chimera/Hevm.sol";
   6 |     | import {Panic} from "@recon/Panic.sol";
   7 |     | import {MockERC20} from "@recon/MockERC20.sol";
   8 |     | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
   9 |     | 
  10 |     | import {BeforeAfter} from "../BeforeAfter.sol";
  11 |     | import {Properties} from "../Properties.sol";
  12 |     | import {ISuperVaultStrategy} from "src/interfaces/SuperVault/ISuperVaultStrategy.sol";
  13 |     | import {YieldSourceType} from "test/recon/managers/YieldManager.sol";
  14 |     | import {MockERC4626Tester} from "test/recon/mocks/MockERC4626Tester.sol";
  15 |     | import {MockERC5115Tester} from "test/recon/mocks/MockERC5115Tester.sol";
  16 |     | import {MockERC7540Tester} from "test/recon/mocks/MockERC7540Tester.sol";
  17 |     | 
  18 |     | abstract contract DoomsdayTargets is BaseTargetFunctions, Properties {
  19 |     |     /// @dev Property: previewDeposit and deposit equivalence
  20 | *r  |     function doomsday_previewDepositEquivalence_ASSERTION_PREVIEW_DEPOSIT_EQUIVALENCE(
  21 |     |         uint256 assets
  22 |     |     ) public stateless {
  23 | *r  |         uint256 previewDepositShares = superVault.previewDeposit(assets);
  24 |     | 
  25 | *   |         vm.prank(_getActor());
  26 | *r  |         uint256 sharesActualDeposit = superVault.deposit(assets, _getActor());
  27 |     | 
  28 | *   |         eq(
  29 | *   |             previewDepositShares,
  30 | *   |             sharesActualDeposit,
  31 | *   |             ASSERTION_PREVIEW_DEPOSIT_EQUIVALENCE
  32 |     |         );
  33 |     |     }
  34 |     | 
  35 |     |     /// @dev Property: previewMint and mint equivalence
  36 | *r  |     function doomsday_previewMintEquivalence_ASSERTION_PREVIEW_MINT_EQUIVALENCE(uint256 shares) public stateless {
  37 | *r  |         uint256 previewMintAssets = superVault.previewMint(shares);
  38 |     | 
  39 | *   |         vm.prank(_getActor());
  40 | *r  |         uint256 assetsActualMint = superVault.mint(shares, _getActor());
  41 |     | 
  42 | *   |         eq(
  43 | *   |             previewMintAssets,
  44 | *   |             assetsActualMint,
  45 | *   |             ASSERTION_PREVIEW_MINT_EQUIVALENCE
  46 |     |         );
  47 |     |     }
  48 |     | 
  49 |     |     /// @dev Property: mint/redeem doesn't cause loss to user
  50 | *r  |     function doomsday_mintRedeemSymmetrical_ASSERTION_MINT_REDEEM_SYMMETRICAL(
  51 |     |         uint256 sharesToMint
  52 | *   |     ) public stateless {
  53 |     |         // skip if there's been any gain because it complicates the assertion checking
  54 |     |         // NOTE: removed because was previously checking that user doesn't gain only from minting/redeeming
  55 |     |         // if (MockERC4626Tester(_getYieldSource()).totalGains() > 0) {
  56 |     |         //     return;
  57 |     |         // }
  58 | *   |         address asset = superVault.asset();
  59 | *   |         uint256 balanceBefore = MockERC20(asset).balanceOf(_getActor());
  60 | *   |         uint256 feeRecipientBalanceBefore = MockERC20(asset).balanceOf(
  61 | *   |             feeRecipient
  62 |     |         );
  63 |     | 
  64 |     |         // 1. Mint
  65 | *   |         vm.prank(_getActor());
  66 | *r  |         uint256 assetsUsed = superVault.mint(sharesToMint, _getActor());
  67 |     | 
  68 |     |         // 2. Deposit assets into yield strategy via executeHooks
  69 |     |         // This is needed because the user's assets are currently in the strategy contract
  70 |     |         // but not yet deposited into the underlying yield source
  71 | *   |         uint256 strategyAssetBalance = MockERC20(asset).balanceOf(
  72 | *   |             address(superVaultStrategy)
  73 |     |         );
  74 | *   |         if (strategyAssetBalance > 0) {
  75 | *   |             ISuperVaultStrategy.ExecuteArgs
  76 | *   |                 memory depositArgs = _createExecuteDepositArgs(
  77 | *   |                     strategyAssetBalance
  78 |     |                 );
  79 |     | 
  80 | *r  |             superVaultStrategy.executeHooks(depositArgs);
  81 |     |         }
  82 |     | 
  83 |     |         // 3. Request Redemption
  84 | *   |         uint256 userShares = superVault.balanceOf(_getActor());
  85 |     |         // get shares of strategy in the deposited yield source
  86 | *   |         uint256 shares = _getSuperVaultStrategyShares();
  87 |     | 
  88 | *   |         vm.prank(_getActor());
  89 | *r  |         superVault.requestRedeem(shares, _getActor(), _getActor());
  90 |     | 
  91 | *   |         uint256 feeBalanceBefore = MockERC20(superVault.asset()).balanceOf(
  92 | *   |             feeRecipient
  93 |     |         );
  94 |     | 
  95 |     |         // 4. Fulfill Redemption from yield strategy
  96 |     |         // Now we need to redeem from the yield strategy to get assets back
  97 | *   |         ISuperVaultStrategy.FulfillArgs
  98 | *   |             memory fulfillArgs = _createFulfillRedeemFromStrategyArgs(shares);
  99 |     | 
 100 |     |         // called by admin address(this)
 101 | *r  |         superVaultStrategy.fulfillRedeemRequests(fulfillArgs);
 102 |     | 
 103 |     |         // 5. Claim Redemption
 104 | *   |         uint256 sharesToRedeem = superVault.maxRedeem(_getActor());
 105 |     | 
 106 | *   |         vm.prank(_getActor());
 107 | *r  |         superVault.redeem(sharesToRedeem, _getActor(), _getActor());
 108 |     | 
 109 | *   |         uint256 balanceAfter = MockERC20(asset).balanceOf(_getActor());
 110 |     | 
 111 | *   |         uint256 TOLERANCE = 10; // 10 wei max tolerance of assets lost
 112 |     | 
 113 | *   |         uint256 feeRecipientBalanceAfter = MockERC20(superVault.asset())
 114 | *   |             .balanceOf(feeRecipient);
 115 | *   |         uint256 feeDelta = feeRecipientBalanceAfter - feeRecipientBalanceBefore;
 116 |     | 
 117 |     |         // 6. Check that user didn't lose assets
 118 | *   |         gte(
 119 | *   |             balanceAfter + TOLERANCE + feeDelta,
 120 | *   |             balanceBefore,
 121 | *   |             ASSERTION_MINT_REDEEM_SYMMETRICAL
 122 |     |         );
 123 |     |     }
 124 |     | 
 125 |     |     /// @dev Property: deposit/withdraw doesn't cause loss to user
 126 | *r  |     function doomsday_depositWithdrawSymmetrical_ASSERTION_DEPOSIT_WITHDRAW_SYMMETRICAL(
 127 |     |         uint256 assetsToDeposit
 128 | *   |     ) public stateless returns (uint256, uint256) {
 129 |     |         // skip if there's been any gain because it complicates the assertion checking
 130 |     |         // NOTE: removed because was previously checking that user doesn't gain only from minting/redeeming
 131 |     |         // if (MockERC4626Tester(_getYieldSource()).totalGains() > 0) {
 132 |     |         //     return;
 133 |     |         // }
 134 | *   |         address asset = superVault.asset();
 135 | *   |         uint256 balanceBefore = MockERC20(asset).balanceOf(_getActor());
 136 |     | 
 137 |     |         // 1. Deposit
 138 | *   |         vm.prank(_getActor());
 139 | *r  |         superVault.deposit(assetsToDeposit, _getActor());
 140 |     | 
 141 |     |         // 2. Request Withdrawal (through redemption in ERC7540)
 142 | *   |         uint256 shares = superVault.balanceOf(_getActor());
 143 | *   |         vm.prank(_getActor());
 144 | *   |         superVault.requestRedeem(shares, _getActor(), _getActor());
 145 |     | 
 146 |     |         // 3. Fulfill Withdrawal
 147 | *   |         ISuperVaultStrategy.FulfillArgs
 148 | *   |             memory fulfillArgs = _createFulfillRedeemArgs(shares);
 149 |     |         // fulfills as admin (address(this))
 150 | *r  |         superVaultStrategy.fulfillRedeemRequests(fulfillArgs);
 151 |     | 
 152 |     |         // 4. Claim Withdrawal
 153 | *   |         uint256 withdrawableAssets = superVault.maxWithdraw(_getActor());
 154 | *   |         vm.prank(_getActor());
 155 | *   |         superVault.withdraw(withdrawableAssets, _getActor(), _getActor());
 156 |     | 
 157 | *   |         uint256 balanceAfter = MockERC20(asset).balanceOf(_getActor());
 158 |     | 
 159 | *   |         uint256 TOLERANCE = 10; // 10 wei max tolerance of assets lost
 160 |     |         // 5. Check that user didn't lose assets
 161 | *   |         gte(
 162 | *   |             balanceAfter + TOLERANCE,
 163 | *   |             balanceBefore,
 164 | *   |             ASSERTION_DEPOSIT_WITHDRAW_SYMMETRICAL
 165 |     |         );
 166 |     | 
 167 | *   |         return (balanceAfter, balanceBefore);
 168 |     |     }
 169 |     | 
 170 |     |     /// @dev Property: maxRedeem is reset to 0 after full redemption
 171 |     |     /// @dev Property: redeeming maxRedeem shouldn't revert
 172 | *r  |     function doomsday_maxRedeemResetsAfterFullRedemption_ASSERTION_MAX_REDEEM_RESETS_AFTER_FULL_REDEMPTION(
 173 |     |         uint256 sharesToMint
 174 |     |     ) public stateless {
 175 |     |         // 1. Deposit to get shares
 176 | *   |         vm.prank(_getActor());
 177 | *r  |         superVault.mint(sharesToMint, _getActor());
 178 |     | 
 179 |     |         // redeem all user shares
 180 | *   |         uint256 shares = superVault.balanceOf(_getActor());
 181 |     | 
 182 |     |         // 2. Request full redemption
 183 | *   |         vm.prank(_getActor());
 184 | *   |         superVault.requestRedeem(shares, _getActor(), _getActor());
 185 |     | 
 186 |     |         // 3. Fulfill the redemption request
 187 | *   |         ISuperVaultStrategy.FulfillArgs
 188 | *   |             memory fulfillArgs = _createFulfillRedeemArgs(shares);
 189 |     |         // fulfill as address(this)
 190 | *r  |         superVaultStrategy.fulfillRedeemRequests(fulfillArgs);
 191 |     | 
 192 |     |         // 4. Check maxRedeem before claiming
 193 | *   |         uint256 maxRedeemBeforeClaim = superVault.maxRedeem(_getActor());
 194 |     | 
 195 |     |         // 5. Claim the full redemption
 196 | *   |         vm.prank(_getActor());
 197 | *   |         try superVault.redeem(maxRedeemBeforeClaim, _getActor(), _getActor()) {
 198 |     |             // 6. Check maxRedeem is reset to 0 after full redemption
 199 | *   |             uint256 maxRedeemAfterClaim = superVault.maxRedeem(_getActor());
 200 | *   |             eq(
 201 | *   |                 maxRedeemAfterClaim,
 202 | *   |                 0,
 203 | *   |                 ASSERTION_MAX_REDEEM_RESETS_AFTER_FULL_REDEMPTION
 204 |     |             );
 205 |     |         } catch {
 206 |     |             if (maxRedeemBeforeClaim > 0) {
 207 |     |                 t(false, ASSERTION_MAX_REDEEM_RESETS_AFTER_FULL_REDEMPTION);
 208 |     |             }
 209 |     |         }
 210 |     |     }
 211 |     | 
 212 |     |     /// @dev Property: maxWithdraw is reset to 0 after full withdrawal
 213 | *r  |     function doomsday_maxWithdrawResetsAfterFullWithdrawal_ASSERTION_MAX_WITHDRAW_RESETS_AFTER_FULL_WITHDRAWAL(
 214 |     |         uint256 assetsToDeposit
 215 |     |     ) public stateless {
 216 |     |         // 1. Deposit to get shares
 217 | *   |         vm.prank(_getActor());
 218 | *r  |         superVault.deposit(assetsToDeposit, _getActor());
 219 |     | 
 220 | *   |         uint256 shares = superVault.balanceOf(_getActor());
 221 |     | 
 222 |     |         // 2. Request redemption of all shares
 223 | *   |         vm.prank(_getActor());
 224 | *   |         superVault.requestRedeem(shares, _getActor(), _getActor());
 225 |     | 
 226 |     |         // 3. Fulfill the redemption request
 227 | *   |         ISuperVaultStrategy.FulfillArgs
 228 | *   |             memory fulfillArgs = _createFulfillRedeemArgs(shares);
 229 |     |         // called as admin address(this)
 230 | *r  |         superVaultStrategy.fulfillRedeemRequests(fulfillArgs);
 231 |     | 
 232 |     |         // 4. Check maxWithdraw after fulfillment and use that value
 233 | *   |         uint256 maxWithdrawBefore = superVault.maxWithdraw(_getActor());
 234 |     | 
 235 |     |         // 5. Withdraw the exact amount returned by maxWithdraw
 236 | *   |         vm.prank(_getActor());
 237 | *   |         try superVault.withdraw(maxWithdrawBefore, _getActor(), _getActor()) {
 238 |     |             // 6. Check maxWithdraw is reset to 0 after full withdrawal
 239 | *   |             uint256 maxWithdrawAfter = superVault.maxWithdraw(_getActor());
 240 | *   |             eq(
 241 | *   |                 maxWithdrawAfter,
 242 | *   |                 0,
 243 | *   |                 ASSERTION_MAX_WITHDRAW_RESETS_AFTER_FULL_WITHDRAWAL
 244 |     |             );
 245 |     |         } catch {
 246 |     |             t(false, ASSERTION_MAX_WITHDRAW_RESETS_AFTER_FULL_WITHDRAWAL);
 247 |     |         }
 248 |     |     }
 249 |     | 
 250 |     |     /// @dev Property: fulfillRedeemRequests doesn't redeem more than requested for multiple actors
 251 | *r  |     function doomsday_fulfillDoesntOverRedeemMultipleActors_ASSERTION_FULFILL_DOESNT_OVER_REDEEM_MULTIPLE_ACTORS(
 252 |     |         uint256[3] memory sharesToMint,
 253 |     |         uint256[3] memory actorIndexes
 254 |     |     ) public stateless {
 255 | *   |         address[] memory actors = _getActors();
 256 | *   |         if (actors.length < 3) return; // Need at least 3 actors for this test
 257 |     | 
 258 |     |         // Arrays to track actors and their requests
 259 | *   |         address[] memory testActors = new address[](3);
 260 | *   |         uint256[] memory requestedShares = new uint256[](3);
 261 | *   |         uint256[] memory sharesBefore = new uint256[](3);
 262 |     | 
 263 |     |         // 1. Setup: Each actor deposits and requests redemption
 264 | *   |         uint256 totalRequestedShares;
 265 | *   |         for (uint256 i = 0; i < 3; i++) {
 266 |     |             // Get unique actor
 267 | *   |             testActors[i] = actors[actorIndexes[i] % actors.length];
 268 |     | 
 269 |     |             // Mint shares for this actor
 270 | *   |             if (sharesToMint[i] > 0) {
 271 | *   |                 vm.prank(testActors[i]);
 272 | *r  |                 superVault.mint(sharesToMint[i], testActors[i]);
 273 |     |             }
 274 |     | 
 275 |     |             // Get actual share balance
 276 | *   |             sharesBefore[i] = superVault.maxRedeem(testActors[i]);
 277 | *   |             requestedShares[i] = sharesBefore[i];
 278 |     | 
 279 |     |             // Request redemption of all shares
 280 | *   |             if (requestedShares[i] > 0) {
 281 | *   |                 vm.prank(testActors[i]);
 282 | *r  |                 superVault.requestRedeem(
 283 | *   |                     requestedShares[i],
 284 | *   |                     testActors[i],
 285 | *   |                     testActors[i]
 286 |     |                 );
 287 |     |             }
 288 | *   |             totalRequestedShares += requestedShares[i];
 289 |     |         }
 290 |     | 
 291 |     |         // 2. Create multi-actor FulfillArgs
 292 | *   |         ISuperVaultStrategy.FulfillArgs
 293 | *   |             memory fulfillArgs = _createMultiActorFulfillArgs(
 294 | *   |                 testActors,
 295 | *   |                 requestedShares
 296 |     |             );
 297 |     | 
 298 |     |         // 3. Calculate total pending before
 299 | *   |         uint256 totalPendingBefore;
 300 | *   |         for (uint256 i = 0; i < 3; i++) {
 301 | *   |             totalPendingBefore += superVault.pendingRedeemRequest(
 302 |     |                 0,
 303 | *   |                 testActors[i]
 304 |     |             );
 305 |     |         }
 306 |     | 
 307 |     |         // 4. Fulfill all redemption requests at once
 308 |     |         // fulfill as address(this)
 309 | *r  |         superVaultStrategy.fulfillRedeemRequests(fulfillArgs);
 310 |     | 
 311 |     |         // 5. Calculate total pending after
 312 |     |         uint256 totalPendingAfter;
 313 |     |         for (uint256 i = 0; i < 3; i++) {
 314 |     |             totalPendingAfter += superVault.pendingRedeemRequest(
 315 |     |                 0,
 316 |     |                 testActors[i]
 317 |     |             );
 318 |     |         }
 319 |     | 
 320 |     |         lte(
 321 |     |             totalPendingBefore - totalPendingAfter,
 322 |     |             totalRequestedShares,
 323 |     |             ASSERTION_FULFILL_DOESNT_OVER_REDEEM_MULTIPLE_ACTORS
 324 |     |         );
 325 |     |     }
 326 |     | 
 327 |     |     /// @dev Property: primary manager can always be replaced by governance via `changePrimaryManager`
 328 | *r  |     function doomsday_primaryManagerAlwaysChangeable_ASSERTION_PRIMARY_MANAGER_ALWAYS_CHANGEABLE() public stateless {
 329 | *   |         address strategy = address(superVaultStrategy);
 330 | *   |         address newManager = _getActor();
 331 |     | 
 332 |     |         // Since address(this) has SUPER_GOVERNOR_ROLE, this should always succeed
 333 | *   |         vm.prank(address(this));
 334 | *   |         try superGovernor.changePrimaryManager(strategy, newManager) {
 335 |     |             // Call succeeded - this is expected behavior
 336 |     |         } catch (bytes memory err) {
 337 |     |             bool expectedError;
 338 |     |             expectedError = checkError(err, "MANAGER_TAKEOVERS_FROZEN()"); // custom error
 339 |     |             t(
 340 |     |                 !expectedError,
 341 |     |                 ASSERTION_PRIMARY_MANAGER_ALWAYS_CHANGEABLE
 342 |     |             );
 343 |     |         }
 344 |     |     }
 345 |     | 
 346 |     |     /// @dev Property: all users can withdraw (solvency)
 347 |     |     // NOTE: if withdrawing from a given strategy via fulfillRedeemRequests fails, it can be expected that one of the YieldSourceTargets would be called to switch the yield source
 348 |     |     // this should allow fulfillments to eventually succeed so we don't need to sort through all yield sources that have currently been deposited into before fulfilling
 349 | *r  |     function doomsday_allUsersCanWithdraw_ASSERTION_ALL_USERS_CAN_WITHDRAW_WHEN_UNPAUSED() public stateless {
 350 | *   |         address[] memory actors = _getActors();
 351 | *   |         bool paused = superVaultAggregator.isStrategyPaused(
 352 | *   |             address(superVaultStrategy)
 353 |     |         );
 354 |     | 
 355 |     |         // request redemption for all actors
 356 | *   |         for (uint256 i; i < actors.length; i++) {
 357 | *   |             uint256 redeemableShares = superVault.balanceOf(actors[i]);
 358 |     | 
 359 | *   |             vm.prank(actors[i]);
 360 | *r  |             superVault.requestRedeem(redeemableShares, actors[i], actors[i]);
 361 |     |         }
 362 |     | 
 363 |     |         // fulfill redemption for all actors
 364 | *   |         for (uint256 i; i < actors.length; i++) {
 365 | *   |             uint256 redeemableShares = superVault.pendingRedeemRequest(
 366 |     |                 0,
 367 | *   |                 actors[i]
 368 |     |             );
 369 |     | 
 370 |     |             // switch the actor
 371 | *   |             _switchActor(i);
 372 |     | 
 373 | *   |             ISuperVaultStrategy.FulfillArgs
 374 | *   |                 memory fulfillArgs = _fulfillRedeemRequestsArgs(
 375 | *   |                     redeemableShares
 376 |     |                 );
 377 | *r  |             superVaultStrategy.fulfillRedeemRequests(fulfillArgs);
 378 |     |         }
 379 |     | 
 380 |     |         // try to withdraw max possible for all actors
 381 |     |         for (uint256 i; i < actors.length; i++) {
 382 |     |             uint256 withdrawable = superVault.maxWithdraw(actors[i]);
 383 |     | 
 384 |     |             if (withdrawable > 0 && !paused) {
 385 |     |                 vm.prank(actors[i]);
 386 |     |                 try
 387 |     |                     superVault.withdraw(withdrawable, actors[i], actors[i])
 388 |     |                 {} catch {
 389 |     |                     // if user can't maxWithdraw there's most likely an insolvency issue related to the TOLERANCE_CONSTANT
 390 |     |                     t(
 391 |     |                         false,
 392 |     |                         ASSERTION_ALL_USERS_CAN_WITHDRAW_WHEN_UNPAUSED
 393 |     |                     );
 394 |     |                 }
 395 |     |             }
 396 |     |         }
 397 |     |     }
 398 |     | 
 399 |     |     /// @dev Property: Claiming redemptions should never revert with INVALID_REDEEM_CLAIM
 400 | *r  |     function doomsday_redemptionsNeverReverts_ASSERTION_REDEEM_SHOULD_NOT_REVERT_INVALID_REDEEM_CLAIM(
 401 |     |         uint256 shares
 402 |     |     ) public asActor stateless {
 403 | *   |         try superVault.redeem(shares, _getActor(), _getActor()) {} catch (
 404 |     |             bytes memory err
 405 | *   |         ) {
 406 | *   |             bool unexpectedError = checkError(err, "INVALID_REDEEM_CLAIM()");
 407 | *   |             t(
 408 | *   |                 !unexpectedError,
 409 | *   |                 ASSERTION_REDEEM_SHOULD_NOT_REVERT_INVALID_REDEEM_CLAIM
 410 |     |             );
 411 |     |         }
 412 |     |     }
 413 |     | 
 414 |     |     /// @dev Get shares for SuperVaultStrategy in the current yield source
 415 | *   |     function _getSuperVaultStrategyShares() internal view returns (uint256) {
 416 | *   |         address yieldSource = _getYieldSource();
 417 | *   |         YieldSourceType sourceType = _getYieldSourceTypeFromAddress(
 418 | *   |             yieldSource
 419 |     |         );
 420 |     | 
 421 | *   |         if (sourceType == YieldSourceType.ERC4626) {
 422 |     |             return
 423 | *   |                 MockERC4626Tester(yieldSource).balanceOf(
 424 | *   |                     address(superVaultStrategy)
 425 |     |                 );
 426 |     |         } else if (sourceType == YieldSourceType.ERC5115) {
 427 |     |             return
 428 |     |                 MockERC5115Tester(yieldSource).balanceOf(
 429 |     |                     address(superVaultStrategy)
 430 |     |                 );
 431 |     |         } else if (sourceType == YieldSourceType.ERC7540) {
 432 |     |             return
 433 |     |                 MockERC7540Tester(yieldSource).balanceOf(
 434 |     |                     address(superVaultStrategy)
 435 |     |                 );
 436 |     |         } else {
 437 |     |             revert("Invalid yield source type");
 438 |     |         }
 439 |     |     }
 440 |     | 
 441 |     |     // Helpers
 442 |     | 
 443 |     |     /// @dev Helper function to clamp the values for the function call
 444 | *r  |     function _fulfillRedeemRequestsArgs(
 445 |     |         uint256 redeemAmount
 446 | *   |     ) public returns (ISuperVaultStrategy.FulfillArgs memory fulfillArgs) {
 447 |     |         // Find a controller that has pending redeem requests
 448 | *   |         address selectedController = _getActor();
 449 | *   |         uint256 pendingAmount = superVaultStrategy.pendingRedeemRequest(
 450 |     |             selectedController
 451 |     |         );
 452 |     | 
 453 |     |         // Clamp using the actor's pending amount
 454 | *   |         uint256 actualRedeemAmount = redeemAmount % (pendingAmount + 1);
 455 |     | 
 456 | *   |         address[] memory controllers = new address[](1);
 457 | *   |         controllers[0] = selectedController;
 458 |     | 
 459 |     |         // Determine yield source type from currently active yield source
 460 | *   |         YieldSourceType activeYieldSourceType = _getYieldSourceTypeFromAddress(
 461 | *   |             _getYieldSource()
 462 |     |         );
 463 | *   |         address redeemHook = _getRedeemHookForType(activeYieldSourceType);
 464 |     | 
 465 |     |         // Create realistic hook calldata for redeem operation
 466 | *   |         bytes memory redeemHookCalldata;
 467 |     | 
 468 | *   |         if (
 469 | *   |             activeYieldSourceType == YieldSourceType.ERC4626 ||
 470 | *   |             activeYieldSourceType == YieldSourceType.ERC5115
 471 |     |         ) {
 472 |     |             // ERC4626/ERC5115 Layout: bytes32 oracleId, address yieldSource, address owner, uint256 shares, bool usePrevAmount
 473 | *   |             redeemHookCalldata = abi.encodePacked(
 474 | *   |                 bytes32(0), // yieldSourceOracleId placeholder
 475 | *   |                 _getYieldSource(), // Current active yield source
 476 | *   |                 address(superVaultStrategy), // Owner (strategy owns the yield source shares)
 477 | *   |                 actualRedeemAmount, // Amount to redeem (matches controller's pending request)
 478 |     |                 false // Don't use previous hook amount
 479 |     |             );
 480 |     |         } else {
 481 |     |             // ERC7540 Layout: bytes32 oracleId, address yieldSource, uint256 shares, bool usePrevAmount
 482 | *   |             redeemHookCalldata = abi.encodePacked(
 483 | *   |                 bytes32(0), // yieldSourceOracleId placeholder
 484 | *   |                 _getYieldSource(), // Current active yield source
 485 | *   |                 actualRedeemAmount, // Amount to redeem (matches controller's pending request)
 486 | *   |                 false // Don't use previous hook amount
 487 |     |             );
 488 |     |         }
 489 |     | 
 490 |     |         // Create arrays for FulfillArgs
 491 | *   |         address[] memory hooks = new address[](1);
 492 | *   |         hooks[0] = redeemHook;
 493 |     | 
 494 | *   |         bytes[] memory hookCalldata = new bytes[](1);
 495 | *   |         hookCalldata[0] = redeemHookCalldata;
 496 |     | 
 497 | *   |         uint256[] memory expectedAssetsOrSharesOut = new uint256[](1);
 498 | *   |         expectedAssetsOrSharesOut[0] = actualRedeemAmount; // Expect amount matching the actual redeem
 499 |     | 
 500 | *   |         bytes32[][] memory globalProofs = new bytes32[][](1);
 501 | *   |         globalProofs[0] = new bytes32[](0); // Empty proof for UnsafeSuperVaultAggregator
 502 |     | 
 503 | *   |         bytes32[][] memory strategyProofs = new bytes32[][](1);
 504 | *   |         strategyProofs[0] = new bytes32[](0); // Empty proof
 505 |     | 
 506 |     |         // Create the FulfillArgs struct
 507 | *   |         fulfillArgs = ISuperVaultStrategy.FulfillArgs({
 508 |     |             controllers: controllers,
 509 |     |             hooks: hooks,
 510 |     |             hookCalldata: hookCalldata,
 511 |     |             expectedAssetsOrSharesOut: expectedAssetsOrSharesOut,
 512 |     |             globalProofs: globalProofs,
 513 |     |             strategyProofs: strategyProofs
 514 |     |         });
 515 |     | 
 516 |     |         return fulfillArgs;
 517 |     |     }
 518 |     | 
 519 |     |     /// @dev Helper function to create FulfillArgs for multiple actors
 520 | *   |     function _createMultiActorFulfillArgs(
 521 |     |         address[] memory controllers,
 522 |     |         uint256[] memory amounts
 523 | *   |     ) internal view returns (ISuperVaultStrategy.FulfillArgs memory) {
 524 | *   |         uint256 numActors = controllers.length;
 525 |     | 
 526 | *   |         address[] memory hooks = new address[](numActors);
 527 | *   |         bytes[] memory hookCalldata = new bytes[](numActors);
 528 | *   |         uint256[] memory expectedAssetsOrSharesOut = new uint256[](numActors);
 529 | *   |         bytes32[][] memory globalProofs = new bytes32[][](numActors);
 530 | *   |         bytes32[][] memory strategyProofs = new bytes32[][](numActors);
 531 |     | 
 532 | *   |         for (uint256 i = 0; i < numActors; i++) {
 533 | *   |             hooks[i] = _getRedeemHookForType(
 534 | *   |                 _getYieldSourceTypeFromAddress(_getYieldSource())
 535 |     |             );
 536 |     | 
 537 | *   |             if (
 538 | *   |                 _getYieldSourceTypeFromAddress(_getYieldSource()) ==
 539 | *   |                 YieldSourceType.ERC4626
 540 |     |             ) {
 541 | *   |                 hookCalldata[i] = abi.encodePacked(
 542 | *   |                     bytes32(0),
 543 | *   |                     _getYieldSource(),
 544 | *   |                     address(superVaultStrategy),
 545 | *   |                     amounts[i],
 546 | *   |                     false
 547 |     |                 );
 548 |     |             } else {
 549 | *   |                 hookCalldata[i] = abi.encodePacked(
 550 | *   |                     bytes32(0),
 551 | *   |                     _getYieldSource(),
 552 | *   |                     amounts[i],
 553 | *   |                     false
 554 |     |                 );
 555 |     |             }
 556 |     | 
 557 | *   |             expectedAssetsOrSharesOut[i] = amounts[i];
 558 | *   |             globalProofs[i] = new bytes32[](0);
 559 | *   |             strategyProofs[i] = new bytes32[](0);
 560 |     |         }
 561 |     | 
 562 |     |         return
 563 | *   |             ISuperVaultStrategy.FulfillArgs({
 564 |     |                 controllers: controllers,
 565 |     |                 hooks: hooks,
 566 |     |                 hookCalldata: hookCalldata,
 567 |     |                 expectedAssetsOrSharesOut: expectedAssetsOrSharesOut,
 568 |     |                 globalProofs: globalProofs,
 569 |     |                 strategyProofs: strategyProofs
 570 |     |             });
 571 |     |     }
 572 |     | 
 573 |     |     /// @dev Helper function to create FulfillArgs for redeem requests
 574 | *   |     function _createFulfillRedeemArgs(
 575 |     |         uint256 amount
 576 | *   |     ) internal view returns (ISuperVaultStrategy.FulfillArgs memory) {
 577 | *   |         address[] memory controllers = new address[](1);
 578 | *   |         controllers[0] = _getActor();
 579 |     | 
 580 | *   |         address[] memory hooks = new address[](1);
 581 | *   |         hooks[0] = _getRedeemHookForType(
 582 | *   |             _getYieldSourceTypeFromAddress(_getYieldSource())
 583 |     |         );
 584 |     | 
 585 | *   |         bytes[] memory hookCalldata = new bytes[](1);
 586 | *   |         if (
 587 | *   |             _getYieldSourceTypeFromAddress(_getYieldSource()) ==
 588 | *   |             YieldSourceType.ERC4626
 589 |     |         ) {
 590 | *   |             hookCalldata[0] = abi.encodePacked(
 591 | *   |                 bytes32(0),
 592 | *   |                 _getYieldSource(),
 593 | *   |                 address(superVaultStrategy),
 594 | *   |                 amount,
 595 |     |                 false
 596 |     |             );
 597 |     |         } else {
 598 | *   |             hookCalldata[0] = abi.encodePacked(
 599 | *   |                 bytes32(0),
 600 | *   |                 _getYieldSource(),
 601 | *   |                 amount,
 602 | *   |                 false
 603 |     |             );
 604 |     |         }
 605 |     | 
 606 | *   |         uint256[] memory expectedAssetsOrSharesOut = new uint256[](1);
 607 | *   |         expectedAssetsOrSharesOut[0] = amount;
 608 |     | 
 609 | *   |         bytes32[][] memory globalProofs = new bytes32[][](1);
 610 | *   |         globalProofs[0] = new bytes32[](0);
 611 |     | 
 612 | *   |         bytes32[][] memory strategyProofs = new bytes32[][](1);
 613 | *   |         strategyProofs[0] = new bytes32[](0);
 614 |     | 
 615 |     |         return
 616 | *   |             ISuperVaultStrategy.FulfillArgs({
 617 |     |                 controllers: controllers,
 618 |     |                 hooks: hooks,
 619 |     |                 hookCalldata: hookCalldata,
 620 |     |                 expectedAssetsOrSharesOut: expectedAssetsOrSharesOut,
 621 |     |                 globalProofs: globalProofs,
 622 |     |                 strategyProofs: strategyProofs
 623 |     |             });
 624 |     |     }
 625 |     | 
 626 |     |     /// @dev Helper function to create ExecuteArgs for depositing assets into yield strategy
 627 | *   |     function _createExecuteDepositArgs(
 628 |     |         uint256 amount
 629 | *   |     ) internal view returns (ISuperVaultStrategy.ExecuteArgs memory) {
 630 | *   |         address[] memory hooks = new address[](1);
 631 | *   |         hooks[0] = _getApproveAndDepositHookForType(
 632 | *   |             _getYieldSourceTypeFromAddress(_getYieldSource())
 633 |     |         );
 634 |     | 
 635 | *   |         bytes[] memory hookCalldata = new bytes[](1);
 636 | *   |         YieldSourceType sourceType = _getYieldSourceTypeFromAddress(
 637 | *   |             _getYieldSource()
 638 |     |         );
 639 |     | 
 640 | *   |         if (sourceType == YieldSourceType.ERC4626) {
 641 |     |             // ERC4626 deposit: bytes32 oracleId, address yieldSource, address token, uint256 assets, bool usePrevAmount
 642 | *   |             hookCalldata[0] = abi.encodePacked(
 643 | *   |                 bytes32(0), // oracle ID placeholder
 644 | *   |                 _getYieldSource(),
 645 | *   |                 superVault.asset(), // token address
 646 | *   |                 amount,
 647 | *   |                 false // don't use previous amount
 648 |     |             );
 649 | *   |         } else if (sourceType == YieldSourceType.ERC5115) {
 650 |     |             // ERC5115 deposit: bytes32 oracleId, address yieldSource, address token, uint256 assets, address receiver, uint256 id, bool usePrevAmount
 651 | *   |             hookCalldata[0] = abi.encodePacked(
 652 | *   |                 bytes32(0),
 653 | *   |                 _getYieldSource(),
 654 | *   |                 superVault.asset(), // token address
 655 |     |                 amount,
 656 | *   |                 address(superVaultStrategy),
 657 |     |                 uint256(0), // sy ID for ERC5115
 658 |     |                 false
 659 |     |             );
 660 | *   |         } else if (sourceType == YieldSourceType.ERC7540) {
 661 |     |             // ERC7540 requestDeposit: bytes32 oracleId, address yieldSource, address token, uint256 assets, address controller, bool usePrevAmount
 662 | *   |             hookCalldata[0] = abi.encodePacked(
 663 | *   |                 bytes32(0),
 664 | *   |                 _getYieldSource(),
 665 | *   |                 superVault.asset(), // token address
 666 |     |                 amount,
 667 | *   |                 address(superVaultStrategy),
 668 |     |                 false
 669 |     |             );
 670 |     |         }
 671 |     | 
 672 | *   |         uint256[] memory expectedAssetsOrSharesOut = new uint256[](1);
 673 |     |         // For deposit hooks, we expect shares back. Calculate expected shares based on yield source conversion
 674 |     |         // Use a very small amount (1) as minimum since we just want the deposit to succeed
 675 | *   |         expectedAssetsOrSharesOut[0] = 1; // Minimum expected shares from deposit
 676 |     | 
 677 | *   |         bytes32[][] memory globalProofs = new bytes32[][](1);
 678 | *   |         globalProofs[0] = new bytes32[](0);
 679 |     | 
 680 | *   |         bytes32[][] memory strategyProofs = new bytes32[][](1);
 681 | *   |         strategyProofs[0] = new bytes32[](0);
 682 |     | 
 683 | *   |         return
 684 | *   |             ISuperVaultStrategy.ExecuteArgs({
 685 | *   |                 hooks: hooks,
 686 | *   |                 hookCalldata: hookCalldata,
 687 | *   |                 expectedAssetsOrSharesOut: expectedAssetsOrSharesOut,
 688 | *   |                 globalProofs: globalProofs,
 689 | *   |                 strategyProofs: strategyProofs
 690 |     |             });
 691 |     |     }
 692 |     | 
 693 |     |     /// @dev Helper function to create FulfillArgs for redeeming from yield strategy
 694 | *   |     function _createFulfillRedeemFromStrategyArgs(
 695 |     |         uint256 sharesToRedeem
 696 | *   |     ) internal view returns (ISuperVaultStrategy.FulfillArgs memory) {
 697 | *   |         address[] memory controllers = new address[](1);
 698 | *   |         controllers[0] = _getActor();
 699 |     | 
 700 |     |         // Get the actual share balance that the SuperVaultStrategy holds in the yield source
 701 | *   |         address yieldSource = _getYieldSource();
 702 | *   |         uint256 strategyYieldSourceShares = IERC20(yieldSource).balanceOf(
 703 | *   |             address(superVaultStrategy)
 704 |     |         );
 705 |     | 
 706 |     |         // Use the pending shares for the hook calldata to match what's expected by fulfillRedeemRequests
 707 | *   |         uint256 pendingShares = superVault.pendingRedeemRequest(0, _getActor());
 708 |     | 
 709 |     |         // For debugging: ensure we don't try to redeem more than the strategy has
 710 | *   |         uint256 actualSharesToRedeem = strategyYieldSourceShares < pendingShares
 711 | *   |             ? strategyYieldSourceShares
 712 | *   |             : pendingShares;
 713 |     | 
 714 | *   |         address[] memory hooks = new address[](1);
 715 | *   |         hooks[0] = _getRedeemHookForType(
 716 | *   |             _getYieldSourceTypeFromAddress(yieldSource)
 717 |     |         );
 718 |     | 
 719 | *   |         bytes[] memory hookCalldata = new bytes[](1);
 720 | *   |         YieldSourceType sourceType = _getYieldSourceTypeFromAddress(
 721 | *   |             yieldSource
 722 |     |         );
 723 |     | 
 724 | *   |         if (
 725 | *   |             sourceType == YieldSourceType.ERC4626 ||
 726 |     |             sourceType == YieldSourceType.ERC5115
 727 |     |         ) {
 728 |     |             // For ERC4626/5115: bytes32 oracleId, address yieldSource, address owner, uint256 shares, bool usePrevAmount
 729 |     |             // Use the calculated shares to redeem (limited by what strategy actually has)
 730 | *   |             hookCalldata[0] = abi.encodePacked(
 731 | *   |                 bytes32(0),
 732 | *   |                 yieldSource,
 733 | *   |                 address(superVaultStrategy), // owner is the strategy
 734 | *   |                 actualSharesToRedeem, // redeem calculated amount
 735 |     |                 false
 736 |     |             );
 737 |     |         } else {
 738 |     |             // For ERC7540: bytes32 oracleId, address yieldSource, uint256 shares, bool usePrevAmount
 739 |     |             hookCalldata[0] = abi.encodePacked(
 740 |     |                 bytes32(0),
 741 |     |                 yieldSource,
 742 |     |                 actualSharesToRedeem, // redeem calculated amount
 743 |     |                 false
 744 |     |             );
 745 |     |         }
 746 |     | 
 747 |     |         // For fulfillment, we expect to get assets back from redeeming the shares
 748 |     |         // Use a conservative estimate for expected assets out
 749 | *   |         uint256[] memory expectedAssetsOrSharesOut = new uint256[](1);
 750 | *   |         expectedAssetsOrSharesOut[0] = actualSharesToRedeem > 0 ? 1 : 0; // Minimum 1 asset expected if redeeming anything
 751 |     | 
 752 | *   |         bytes32[][] memory globalProofs = new bytes32[][](1);
 753 | *   |         globalProofs[0] = new bytes32[](0);
 754 |     | 
 755 | *   |         bytes32[][] memory strategyProofs = new bytes32[][](1);
 756 | *   |         strategyProofs[0] = new bytes32[](0);
 757 |     | 
 758 |     |         return
 759 | *   |             ISuperVaultStrategy.FulfillArgs({
 760 |     |                 controllers: controllers,
 761 |     |                 hooks: hooks,
 762 |     |                 hookCalldata: hookCalldata,
 763 |     |                 expectedAssetsOrSharesOut: expectedAssetsOrSharesOut,
 764 |     |                 globalProofs: globalProofs,
 765 |     |                 strategyProofs: strategyProofs
 766 |     |             });
 767 |     |     }
 768 |     | }
 769 |     | 

/opt/scfuzzbench/work/target/test/recon/targets/ManagersTargets.sol
  1 |     | // SPDX-License-Identifier: GPL-2.0
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
  5 |     | import {BeforeAfter} from "../BeforeAfter.sol";
  6 |     | import {Properties} from "../Properties.sol";
  7 |     | import {vm} from "@chimera/Hevm.sol";
  8 |     | 
  9 |     | import {MockERC20} from "@recon/MockERC20.sol";
 10 |     | 
 11 |     | // Target functions that are effectively inherited from the Actor and AssetManagers
 12 |     | // Once properly standardized, managers will expose these by default
 13 |     | // Keeping them out makes your project more custom
 14 |     | abstract contract ManagersTargets is BaseTargetFunctions, Properties {
 15 |     |     // == ACTOR HANDLERS == //
 16 |     | 
 17 |     |     /// @dev Start acting as another actor
 18 |     |     /// @dev Update ghosts here to make global property checks not fail falsely
 19 | *r  |     function switchActor(uint256 entropy) public updateGhosts {
 20 | *   |         _switchActor(entropy);
 21 |     |     }
 22 |     | 
 23 |     |     /// @dev Starts using a new asset
 24 | *r  |     function switch_asset(uint256 entropy) public {
 25 | *   |         _switchAsset(entropy);
 26 |     |     }
 27 |     | 
 28 |     |     /// @dev Deploy a new token and add it to the list of assets, then set it as the current asset
 29 | *r  |     function add_new_asset(uint8 decimals) public returns (address) {
 30 | *   |         address newAsset = _newAsset(decimals);
 31 |     |         return newAsset;
 32 |     |     }
 33 |     | 
 34 |     |     /// @dev Switches the current vault based on the entropy
 35 |     |     /// @param entropy The entropy to choose a random vault in the array for switching
 36 | *r  |     function switch_vault(uint256 entropy) public {
 37 | *   |         _switchVault(entropy);
 38 |     |     }
 39 |     | 
 40 |     |     /// @dev Deploy a new vault using the current asset and add it to the list of vaults,
 41 |     |     /// then set it as the current vault
 42 | *r  |     function add_new_vault() public {
 43 | *   |         _newVault(superVault.asset());
 44 |     |     }
 45 |     | 
 46 |     |     /// === GHOST UPDATING HANDLERS ===///
 47 |     |     /// We `updateGhosts` cause you never know (e.g. donations)
 48 |     |     /// If you don't want to track donations, remove the `updateGhosts`
 49 |     | 
 50 |     |     /// @dev Approve to arbitrary address, uses Actor by default
 51 |     |     /// NOTE: You're almost always better off setting approvals in `Setup`
 52 | *r  |     function asset_approve(
 53 |     |         address to,
 54 |     |         uint128 amt
 55 |     |     ) public updateGhosts asActor {
 56 | *   |         MockERC20(superVault.asset()).approve(to, amt);
 57 |     |     }
 58 |     | 
 59 |     |     /// @dev Mint to arbitrary address, uses owner by default, even though MockERC20 doesn't check
 60 | *r  |     function asset_mint(address to, uint128 amt) public updateGhosts asAdmin {
 61 | *   |         MockERC20(superVault.asset()).mint(to, amt);
 62 |     |     }
 63 |     | }
 64 |     | 

/opt/scfuzzbench/work/target/test/recon/targets/OracleTargets.sol
  1 |     | // SPDX-License-Identifier: GPL-2.0
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | // External dependencies
  5 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
  6 |     | import {vm} from "@chimera/Hevm.sol";
  7 |     | import {Panic} from "@recon/Panic.sol";
  8 |     | 
  9 |     | // Source dependencies
 10 |     | import {IECDSAPPSOracle} from "src/interfaces/oracles/IECDSAPPSOracle.sol";
 11 |     | import "test/mocks/MockYieldSourceOracle.sol";
 12 |     | import "../mocks/MockERC4626YieldSourceOracle.sol";
 13 |     | import "../mocks/MockERC5115YieldSourceOracle.sol";
 14 |     | import "../mocks/MockERC7540YieldSourceOracle.sol";
 15 |     | 
 16 |     | // Test suite dependencies
 17 |     | import {BeforeAfter} from "../BeforeAfter.sol";
 18 |     | import {Properties} from "../Properties.sol";
 19 |     | 
 20 |     | abstract contract OracleTargets is BaseTargetFunctions, Properties {
 21 |     |     /// CUSTOM TARGET FUNCTIONS - Add your own target functions here ///
 22 | *r  |     function yieldSourceOracle_setValidAsset_clamped() public {
 23 | *   |         mockERC4626YieldSourceOracle_setValidAsset(superVault.asset(), true);
 24 |     |     }
 25 |     | 
 26 | *r  |     function mockERC4626YieldSourceOracle_setValidAsset(
 27 |     |         address asset,
 28 |     |         bool isValid
 29 |     |     ) public asActor {
 30 | *   |         MockERC4626YieldSourceOracle(address(erc4626YieldSourceOracle))
 31 |     |             .setValidAsset(asset, isValid);
 32 |     |     }
 33 |     | 
 34 | *r  |     function mockERC5115YieldSourceOracle_setValidAsset(
 35 |     |         address asset,
 36 |     |         bool isValid
 37 |     |     ) public asActor {
 38 | *   |         MockERC5115YieldSourceOracle(address(erc5115YieldSourceOracle))
 39 |     |             .setValidAsset(asset, isValid);
 40 |     |     }
 41 |     | 
 42 | *r  |     function mockERC7540YieldSourceOracle_setValidAsset(
 43 |     |         address asset,
 44 |     |         bool isValid
 45 |     |     ) public asActor {
 46 | *   |         MockERC7540YieldSourceOracle(address(erc7540YieldSourceOracle))
 47 |     |             .setValidAsset(asset, isValid);
 48 |     |     }
 49 |     | 
 50 | *r  |     function ECDSAPPSOracle_updatePPS_clamped(uint256 pps) public {
 51 | *   |         pps %= (100_000_000 * 1e18) + 1; // clamp to a reasonable max price
 52 |     | 
 53 | *   |         address[] memory strategies = new address[](1);
 54 | *   |         strategies[0] = address(superVaultStrategy);
 55 |     | 
 56 | *   |         bytes[][] memory proofsArray = new bytes[][](1);
 57 | *   |         proofsArray[0] = new bytes[](0);
 58 |     | 
 59 | *   |         uint256[] memory ppss = new uint256[](1);
 60 | *   |         ppss[0] = pps;
 61 |     | 
 62 | *   |         uint256[] memory ppsStdevs = new uint256[](1);
 63 | *   |         ppsStdevs[0] = 0;
 64 |     | 
 65 | *   |         uint256[] memory validatorSets = new uint256[](1);
 66 | *   |         validatorSets[0] = 0;
 67 |     | 
 68 | *   |         uint256[] memory totalValidators = new uint256[](1);
 69 | *   |         totalValidators[0] = 0;
 70 |     | 
 71 | *   |         uint256[] memory timestamps = new uint256[](1);
 72 | *   |         timestamps[0] = block.timestamp;
 73 |     | 
 74 | *   |         IECDSAPPSOracle.UpdatePPSArgs memory args = IECDSAPPSOracle
 75 |     |             .UpdatePPSArgs({
 76 | *   |                 strategies: strategies,
 77 | *   |                 proofsArray: proofsArray,
 78 | *   |                 ppss: ppss,
 79 | *   |                 ppsStdevs: ppsStdevs,
 80 | *   |                 validatorSets: validatorSets,
 81 | *   |                 totalValidators: totalValidators,
 82 | *   |                 timestamps: timestamps
 83 |     |             });
 84 |     | 
 85 | *   |         ECDSAPPSOracle_updatePPS(args);
 86 |     |     }
 87 |     | 
 88 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
 89 | *r  |     function ECDSAPPSOracle_updatePPS(
 90 |     |         IECDSAPPSOracle.UpdatePPSArgs memory args
 91 |     |     ) public asActor {
 92 | *r  |         ECDSAPPSOracle.updatePPS(args);
 93 |     | 
 94 | *   |         hasUpdatedPPS = true;
 95 |     |     }
 96 |     | }
 97 |     | 

/opt/scfuzzbench/work/target/test/recon/targets/SuperGovernorTargets.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
   5 |     | import {BeforeAfter} from "../BeforeAfter.sol";
   6 |     | import {Properties} from "../Properties.sol";
   7 |     | // Chimera deps
   8 |     | import {vm} from "@chimera/Hevm.sol";
   9 |     | 
  10 |     | // Helpers
  11 |     | import {Panic} from "@recon/Panic.sol";
  12 |     | 
  13 |     | import "src/SuperGovernor.sol";
  14 |     | 
  15 |     | abstract contract SuperGovernorTargets is BaseTargetFunctions, Properties {
  16 |     |     /// CUSTOM TARGET FUNCTIONS - Add your own target functions here ///
  17 | *r  |     function superGovernor_proposeGlobalHooksRoot_clamped(
  18 |     |         bytes32 newRoot
  19 |     |     ) public {
  20 | *   |         (bytes32 testRoot, bytes32[][] memory testProofs) = merkleHelper
  21 |     |             .generateTestHooksRoot(
  22 | *   |                 address(approveAndDeposit4626Hook),
  23 | *   |                 address(redeem4626Hook),
  24 | *   |                 _getYieldSource(),
  25 | *   |                 superVault.asset()
  26 |     |             );
  27 |     | 
  28 | *   |         superGovernor_proposeGlobalHooksRoot(testRoot);
  29 |     |     }
  30 |     | 
  31 | *r  |     function superGovernor_proposeUpkeepPaymentsChange_clamped() public {
  32 | *   |         superGovernor_proposeUpkeepPaymentsChange(true);
  33 |     |     }
  34 |     | 
  35 | *r  |     function superGovernor_proposeFee_clamped(
  36 |     |         uint256 feeTypeAsUint,
  37 |     |         uint256 value
  38 |     |     ) public {
  39 | *   |         feeTypeAsUint %= 3;
  40 | *   |         superGovernor_proposeFee(FeeType(feeTypeAsUint), value);
  41 |     |     }
  42 |     | 
  43 | *r  |     function superGovernor_executeFeeUpdate_clamped(
  44 |     |         uint256 feeTypeAsUint
  45 |     |     ) public {
  46 | *   |         feeTypeAsUint %= 3;
  47 | *   |         superGovernor_executeFeeUpdate(FeeType(feeTypeAsUint));
  48 |     |     }
  49 |     | 
  50 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
  51 |     | 
  52 | *r  |     function superGovernor_proposeFee(
  53 |     |         FeeType feeType,
  54 |     |         uint256 value
  55 |     |     ) public asAdmin {
  56 | *r  |         superGovernor.proposeFee(feeType, value);
  57 |     |     }
  58 |     | 
  59 | *r  |     function superGovernor_executeFeeUpdate(FeeType feeType) public asAdmin {
  60 | *   |         superGovernor.executeFeeUpdate(feeType);
  61 |     |     }
  62 |     | 
  63 | *r  |     function superGovernor_proposeMinStaleness(
  64 |     |         uint256 newMinStaleness
  65 |     |     ) public asAdmin {
  66 | *   |         superGovernor.proposeMinStaleness(newMinStaleness);
  67 |     |     }
  68 |     | 
  69 | *r  |     function superGovernor_executeMinStalenesChange() public asAdmin {
  70 | *   |         superGovernor.executeMinStalenesChange();
  71 |     |     }
  72 |     | 
  73 | *r  |     function superGovernor_executeRemoveIncentiveTokens() public asAdmin {
  74 | *   |         superGovernor.executeRemoveIncentiveTokens();
  75 |     |     }
  76 |     | 
  77 | *r  |     function superGovernor_executeUpkeepClaim(uint256 amount) public asAdmin {
  78 | *r  |         superGovernor.executeUpkeepClaim(amount);
  79 |     |     }
  80 |     | 
  81 | *r  |     function superGovernor_proposeUpkeepPaymentsChange(
  82 |     |         bool enabled
  83 |     |     ) public asAdmin {
  84 | *   |         superGovernor.proposeUpkeepPaymentsChange(enabled);
  85 |     |     }
  86 |     | 
  87 | *r  |     function superGovernor_executeUpkeepPaymentsChange() public asAdmin {
  88 | *   |         superGovernor.executeUpkeepPaymentsChange();
  89 |     |     }
  90 |     | 
  91 | *r  |     function superGovernor_proposeAddIncentiveTokens(
  92 |     |         address[] memory tokens
  93 |     |     ) public asAdmin {
  94 | *   |         superGovernor.proposeAddIncentiveTokens(tokens);
  95 |     |     }
  96 |     | 
  97 | *r  |     function superGovernor_executeAddIncentiveTokens() public asAdmin {
  98 | *   |         superGovernor.executeAddIncentiveTokens();
  99 |     |     }
 100 |     | 
 101 | *r  |     function superGovernor_proposeGlobalHooksRoot(
 102 |     |         bytes32 newRoot
 103 |     |     ) public asAdmin {
 104 | *   |         superGovernor.proposeGlobalHooksRoot(newRoot);
 105 |     |     }
 106 |     | }
 107 |     | 

/opt/scfuzzbench/work/target/test/recon/targets/SuperVaultAggregatorTargets.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
   5 |     | import {vm} from "@chimera/Hevm.sol";
   6 |     | import {Panic} from "@recon/Panic.sol";
   7 |     | 
   8 |     | import {ISuperVaultStrategy} from "src/interfaces/SuperVault/ISuperVaultStrategy.sol";
   9 |     | import "src/SuperVault/SuperVaultAggregator.sol";
  10 |     | 
  11 |     | import {BeforeAfter} from "../BeforeAfter.sol";
  12 |     | import {Properties} from "../Properties.sol";
  13 |     | 
  14 |     | abstract contract SuperVaultAggregatorTargets is
  15 |     |     BaseTargetFunctions,
  16 |     |     Properties
  17 |     | {
  18 |     |     /// CUSTOM TARGET FUNCTIONS - Add your own target functions here ///
  19 | *r  |     function superVaultAggregator_proposeChangePrimaryManager_clamped() public {
  20 | *   |         superVaultAggregator_proposeChangePrimaryManager(
  21 | *   |             address(superVaultStrategy),
  22 | *   |             _getActor()
  23 |     |         );
  24 |     |     }
  25 |     | 
  26 | *r  |     function superVaultAggregator_executeChangePrimaryManager_clamped() public {
  27 | *   |         superVaultAggregator_executeChangePrimaryManager(
  28 | *   |             address(superVaultStrategy)
  29 |     |         );
  30 |     |     }
  31 |     | 
  32 | *r  |     function superVaultAggregator_createVault_clamped(
  33 |     |         uint256 minUpdateInterval,
  34 |     |         uint256 maxStaleness,
  35 |     |         uint256 performanceFeeBps,
  36 |     |         uint256 managementFeeBps
  37 |     |     ) public {
  38 |     |         // Clamp values to reasonable ranges
  39 | *   |         minUpdateInterval = minUpdateInterval % 3601; // Max 1 hour
  40 | *   |         maxStaleness = (maxStaleness % 86400) + 301; // Between 5 minutes and 1 day
  41 | *   |         performanceFeeBps = performanceFeeBps % 9001; // Max 90%
  42 | *   |         managementFeeBps = managementFeeBps % 5001; // Max 50%
  43 |     | 
  44 |     |         // Create secondary managers array
  45 | *   |         address[] memory secondaryManagers = new address[](1);
  46 |     | 
  47 | *   |         ISuperVaultAggregator.VaultCreationParams
  48 | *   |             memory params = ISuperVaultAggregator.VaultCreationParams({
  49 | *   |                 asset: _getAsset(),
  50 |     |                 name: "SuperVault",
  51 |     |                 symbol: "SV",
  52 | *   |                 mainManager: address(this),
  53 | *   |                 secondaryManagers: secondaryManagers,
  54 | *   |                 minUpdateInterval: minUpdateInterval,
  55 | *   |                 maxStaleness: maxStaleness,
  56 | *   |                 feeConfig: ISuperVaultStrategy.FeeConfig({
  57 | *   |                     performanceFeeBps: performanceFeeBps,
  58 | *   |                     managementFeeBps: managementFeeBps,
  59 | *   |                     recipient: address(this)
  60 |     |                 })
  61 |     |             });
  62 |     | 
  63 | *   |         superVaultAggregator_createVault(params);
  64 |     |     }
  65 |     | 
  66 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
  67 |     | 
  68 | *r  |     function superVaultAggregator_addAuthorizedCaller(
  69 |     |         address strategy,
  70 |     |         address caller
  71 |     |     ) public asAdmin {
  72 | *   |         superVaultAggregator.addAuthorizedCaller(strategy, caller);
  73 |     |     }
  74 |     | 
  75 | *r  |     function superVaultAggregator_addSecondaryManager(
  76 |     |         address strategy,
  77 |     |         address manager
  78 |     |     ) public asActor {
  79 | *   |         superVaultAggregator.addSecondaryManager(strategy, manager);
  80 |     |     }
  81 |     | 
  82 |     |     /// @dev removed because only callable by oracle
  83 |     |     // function superVaultAggregator_batchForwardPPS(
  84 |     |     //     ISuperVaultAggregator.BatchForwardPPSArgs memory args
  85 |     |     // ) public asActor {
  86 |     |     //     superVaultAggregator.batchForwardPPS(args);
  87 |     |     // }
  88 |     | 
  89 |     |     /// @dev irrelevant for testing because we're bypassing hook validation
  90 |     |     // function superVaultAggregator_changeGlobalLeavesStatus(
  91 |     |     //     bytes32[] memory leaves,
  92 |     |     //     bool[] memory statuses,
  93 |     |     //     address strategy
  94 |     |     // ) public asActor {
  95 |     |     //     superVaultAggregator.changeGlobalLeavesStatus(
  96 |     |     //         leaves,
  97 |     |     //         statuses,
  98 |     |     //         strategy
  99 |     |     //     );
 100 |     |     // }
 101 |     | 
 102 | *r  |     function superVaultAggregator_claimUpkeep(uint256 amount) public asActor {
 103 | *   |         superVaultAggregator.claimUpkeep(amount);
 104 |     |     }
 105 |     | 
 106 | *r  |     function superVaultAggregator_createVault(
 107 |     |         ISuperVaultAggregator.VaultCreationParams memory params
 108 |     |     ) public asActor {
 109 |     |         (
 110 | *   |             address _superVault,
 111 |     |             address _strategy,
 112 |     |             address _escrow
 113 | *r  |         ) = superVaultAggregator.createVault(params);
 114 |     | 
 115 | *   |         superVault = SuperVault(_superVault);
 116 | *   |         superVaultStrategy = SuperVaultStrategy(payable(_strategy));
 117 | *   |         superVaultEscrow = SuperVaultEscrow(_escrow);
 118 |     | 
 119 | *   |         hasDeployedNewVault = true;
 120 |     |     }
 121 |     | 
 122 | *r  |     function superVaultAggregator_depositStake(
 123 |     |         address manager,
 124 |     |         uint256 amount
 125 |     |     ) public asActor {
 126 | *   |         superVaultAggregator.depositStake(manager, amount);
 127 |     |     }
 128 |     | 
 129 | *r  |     function superVaultAggregator_depositUpkeep(uint256 amount) public asActor {
 130 | *   |         superVaultAggregator.depositUpkeep(_getActor(), amount);
 131 |     |     }
 132 |     | 
 133 | *r  |     function superVaultAggregator_executeChangePrimaryManager(
 134 |     |         address strategy
 135 |     |     ) public asActor {
 136 | *   |         superVaultAggregator.executeChangePrimaryManager(strategy);
 137 |     |     }
 138 |     | 
 139 |     |     /// @dev removed because we're bypassing hook validation
 140 |     |     // function superVaultAggregator_executeStrategyHooksRootUpdate(
 141 |     |     //     address strategy
 142 |     |     // ) public asActor {
 143 |     |     //     superVaultAggregator.executeStrategyHooksRootUpdate(strategy);
 144 |     |     // }
 145 |     | 
 146 |     |     /// @dev removed because only callable by oracle
 147 |     |     // function superVaultAggregator_forwardPPS(
 148 |     |     //     address updateAuthority,
 149 |     |     //     ISuperVaultAggregator.ForwardPPSArgs memory args
 150 |     |     // ) public asActor {
 151 |     |     //     superVaultAggregator.forwardPPS(updateAuthority, args);
 152 |     |     // }
 153 |     | 
 154 | *r  |     function superVaultAggregator_proposeChangePrimaryManager(
 155 |     |         address strategy,
 156 |     |         address newManager
 157 |     |     ) public asActor {
 158 | *   |         superVaultAggregator.proposeChangePrimaryManager(strategy, newManager);
 159 |     |     }
 160 |     | 
 161 |     |     /// @dev removed because we're bypassing hook validation
 162 |     |     // function superVaultAggregator_proposeStrategyHooksRoot(
 163 |     |     //     address strategy,
 164 |     |     //     bytes32 newRoot
 165 |     |     // ) public asActor {
 166 |     |     //     superVaultAggregator.proposeStrategyHooksRoot(strategy, newRoot);
 167 |     |     // }
 168 |     | 
 169 | *r  |     function superVaultAggregator_removeAuthorizedCaller(
 170 |     |         address strategy,
 171 |     |         address caller
 172 |     |     ) public asActor {
 173 | *   |         superVaultAggregator.removeAuthorizedCaller(strategy, caller);
 174 |     |     }
 175 |     | 
 176 | *r  |     function superVaultAggregator_removeSecondaryManager(
 177 |     |         address strategy,
 178 |     |         address manager
 179 |     |     ) public asActor {
 180 | *   |         superVaultAggregator.removeSecondaryManager(strategy, manager);
 181 |     |     }
 182 |     | 
 183 | *r  |     function superVaultAggregator_updatePPSVerificationThresholds(
 184 |     |         address strategy,
 185 |     |         uint256 dispersionThreshold_,
 186 |     |         uint256 deviationThreshold_,
 187 |     |         uint256 mnThreshold_
 188 |     |     ) public asActor {
 189 | *   |         superVaultAggregator.updatePPSVerificationThresholds(
 190 |     |             strategy,
 191 |     |             dispersionThreshold_,
 192 |     |             deviationThreshold_,
 193 |     |             mnThreshold_
 194 |     |         );
 195 |     |     }
 196 |     | 
 197 | *r  |     function superVaultAggregator_withdrawStake(uint256 amount) public asActor {
 198 | *   |         superVaultAggregator.withdrawStake(amount);
 199 |     |     }
 200 |     | 
 201 | *r  |     function superVaultAggregator_withdrawUpkeep(
 202 |     |         uint256 amount
 203 |     |     ) public asActor {
 204 | *   |         superVaultAggregator.withdrawUpkeep(amount);
 205 |     |     }
 206 |     | }
 207 |     | 

/opt/scfuzzbench/work/target/test/recon/targets/SuperVaultEscrowTargets.sol
  1 |     | // SPDX-License-Identifier: GPL-2.0
  2 |     | pragma solidity ^0.8.0;
  3 |     | 
  4 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
  5 |     | import {BeforeAfter} from "../BeforeAfter.sol";
  6 |     | import {Properties} from "../Properties.sol";
  7 |     | // Chimera deps
  8 |     | import {vm} from "@chimera/Hevm.sol";
  9 |     | 
 10 |     | // Helpers
 11 |     | import {Panic} from "@recon/Panic.sol";
 12 |     | 
 13 |     | import "src/SuperVault/SuperVaultEscrow.sol";
 14 |     | 
 15 |     | abstract contract SuperVaultEscrowTargets is
 16 |     |     BaseTargetFunctions,
 17 |     |     Properties
 18 |     | {
 19 |     |     /// CUSTOM TARGET FUNCTIONS - Add your own target functions here ///
 20 |     | 
 21 |     | 
 22 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
 23 |     | 
 24 | *r  |     function superVaultEscrow_escrowShares(address from, uint256 amount) public asActor {
 25 | *   |         superVaultEscrow.escrowShares(from, amount);
 26 |     |     }
 27 |     | 
 28 | *r  |     function superVaultEscrow_initialize(address vaultAddress, address strategyAddress) public asActor {
 29 | *   |         superVaultEscrow.initialize(vaultAddress, strategyAddress);
 30 |     |     }
 31 |     | 
 32 | *r  |     function superVaultEscrow_returnShares(address to, uint256 amount) public asActor {
 33 | *   |         superVaultEscrow.returnShares(to, amount);
 34 |     |     }
 35 |     | }

/opt/scfuzzbench/work/target/test/recon/targets/SuperVaultStrategyTargets.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
   5 |     | 
   6 |     | import {vm} from "@chimera/Hevm.sol";
   7 |     | import {Panic} from "@recon/Panic.sol";
   8 |     | import {MockERC20} from "@recon/MockERC20.sol";
   9 |     | 
  10 |     | import "src/SuperVault/SuperVaultStrategy.sol";
  11 |     | 
  12 |     | import {YieldSourceType} from "test/recon/managers/YieldManager.sol";
  13 |     | import {BeforeAfter, OpType} from "../BeforeAfter.sol";
  14 |     | import {Properties} from "../Properties.sol";
  15 |     | 
  16 |     | abstract contract SuperVaultStrategyTargets is BaseTargetFunctions, Properties {
  17 |     |     /// CUSTOM TARGET FUNCTIONS - Add your own target functions here ///
  18 |     | 
  19 |     |     /// @dev Clamps the action type to 0 to add a vault as a yield source
  20 | *r  |     function superVaultStrategy_manageYieldSource_clamped(
  21 |     |         uint256 sourceType
  22 |     |     ) public {
  23 | *   |         YieldSourceType clampedType = YieldSourceType(sourceType % 3); // 0=ERC4626, 1=ERC5115, 2=ERC7540
  24 | *   |         address yieldSourceOracle = _getYieldSourceOracleForType(clampedType);
  25 |     | 
  26 | *   |         superVaultStrategy_manageYieldSource(
  27 | *   |             _getYieldSource(),
  28 | *   |             yieldSourceOracle,
  29 | *   |             0
  30 |     |         );
  31 |     |     }
  32 |     | 
  33 | *r  |     function superVaultStrategy_handleOperations7540_clamped(
  34 |     |         uint256 operation,
  35 |     |         uint256 amount
  36 |     |     ) public {
  37 | *   |         operation %= 7; // clamp by the possible operation types in the enum
  38 | *   |         superVaultStrategy_handleOperations7540(
  39 | *   |             ISuperVaultStrategy.Operation(operation),
  40 |     |             _getActor(),
  41 |     |             _getActor(),
  42 | *   |             amount
  43 |     |         );
  44 |     |     }
  45 |     | 
  46 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
  47 |     | 
  48 | *r  |     function superVaultStrategy_executeVaultFeeConfigUpdate() public asActor {
  49 | *r  |         superVaultStrategy.executeVaultFeeConfigUpdate();
  50 |     |     }
  51 |     | 
  52 | *r  |     function superVaultStrategy_handleOperations4626Deposit(
  53 |     |         address controller,
  54 |     |         uint256 assetsGross
  55 |     |     ) public asActor {
  56 | *r  |         superVaultStrategy.handleOperations4626Deposit(controller, assetsGross);
  57 |     |     }
  58 |     | 
  59 | *r  |     function superVaultStrategy_handleOperations4626Mint(
  60 |     |         address controller,
  61 |     |         uint256 sharesNet,
  62 |     |         uint256 assetsGross,
  63 |     |         uint256 assetsNet
  64 |     |     ) public asActor {
  65 | *r  |         superVaultStrategy.handleOperations4626Mint(
  66 |     |             controller,
  67 |     |             sharesNet,
  68 |     |             assetsGross,
  69 |     |             assetsNet
  70 |     |         );
  71 |     |     }
  72 |     | 
  73 | *r  |     function superVaultStrategy_handleOperations7540(
  74 |     |         ISuperVaultStrategy.Operation operation,
  75 |     |         address controller,
  76 |     |         address receiver,
  77 |     |         uint256 amount
  78 |     |     ) public asActor {
  79 | *   |         superVaultStrategy.handleOperations7540(
  80 | *   |             operation,
  81 | *   |             controller,
  82 | *   |             receiver,
  83 | *   |             amount
  84 |     |         );
  85 |     |     }
  86 |     | 
  87 | *r  |     function superVaultStrategy_manageEmergencyWithdraw(
  88 |     |         uint8 action,
  89 |     |         address recipient,
  90 |     |         uint256 amount
  91 |     |     ) public asActor {
  92 | *   |         superVaultStrategy.manageEmergencyWithdraw(action, recipient, amount);
  93 |     |     }
  94 |     | 
  95 | *r  |     function superVaultStrategy_manageYieldSource(
  96 |     |         address source,
  97 |     |         address oracle,
  98 |     |         uint8 actionType
  99 |     |     ) public asActor {
 100 | *r  |         superVaultStrategy.manageYieldSource(source, oracle, actionType);
 101 |     |     }
 102 |     | 
 103 | *r  |     function superVaultStrategy_manageYieldSources(
 104 |     |         address[] memory sources,
 105 |     |         address[] memory oracles,
 106 |     |         uint8[] memory actionTypes
 107 |     |     ) public asActor {
 108 | *   |         superVaultStrategy.manageYieldSources(sources, oracles, actionTypes);
 109 |     |     }
 110 |     | 
 111 | *r  |     function superVaultStrategy_moveAccumulatorOnTransfer(
 112 |     |         address from,
 113 |     |         address to,
 114 |     |         uint256 shares
 115 |     |     ) public asActor {
 116 | *   |         superVaultStrategy.moveAccumulatorOnTransfer(from, to, shares);
 117 |     |     }
 118 |     | 
 119 | *r  |     function superVaultStrategy_proposeVaultFeeConfigUpdate(
 120 |     |         uint256 performanceFeeBps,
 121 |     |         uint256 managementFeeBps,
 122 |     |         address recipient
 123 |     |     ) public asActor {
 124 | *   |         superVaultStrategy.proposeVaultFeeConfigUpdate(
 125 |     |             performanceFeeBps,
 126 |     |             managementFeeBps,
 127 |     |             recipient
 128 |     |         );
 129 |     |     }
 130 |     | 
 131 | *r  |     function superVaultStrategy_updateMaxPPSSlippage(
 132 |     |         uint256 maxSlippageBps
 133 |     |     ) public asActor {
 134 | *   |         superVaultStrategy.updateMaxPPSSlippage(maxSlippageBps);
 135 |     |     }
 136 |     | }
 137 |     | 

/opt/scfuzzbench/work/target/test/recon/targets/SuperVaultTargets.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | // Recon deps
   5 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
   6 |     | import {vm} from "@chimera/Hevm.sol";
   7 |     | import {Panic} from "@recon/Panic.sol";
   8 |     | import {MockERC20} from "@recon/MockERC20.sol";
   9 |     | 
  10 |     | import "src/SuperVault/SuperVault.sol";
  11 |     | 
  12 |     | import {BeforeAfter, OpType} from "test/recon/BeforeAfter.sol";
  13 |     | import {Properties} from "../Properties.sol";
  14 |     | 
  15 |     | /// @dev All receivers are inherently clamped to actors to make checking properties easier
  16 |     | abstract contract SuperVaultTargets is BaseTargetFunctions, Properties {
  17 |     |     /// CUSTOM TARGET FUNCTIONS - Add your own target functions here ///
  18 | *r  |     function superVault_requestRedeem_clamped(uint256 shares) public {
  19 | *   |         shares %= superVault.balanceOf(_getActor()) + 1;
  20 |     | 
  21 | *   |         superVault_requestRedeem(shares);
  22 |     |     }
  23 |     | 
  24 | *r  |     function superVault_redeem_clamped(uint256 shares) public {
  25 | *   |         uint256 claimableAssets = superVault.maxWithdraw(_getActor());
  26 | *   |         uint256 claimableShares = superVault.convertToShares(claimableAssets);
  27 |     | 
  28 | *   |         shares %= claimableShares + 1;
  29 |     | 
  30 | *   |         superVault_redeem(shares);
  31 |     |     }
  32 |     | 
  33 | *r  |     function superVault_withdraw_clamped(uint256 assets) public {
  34 | *   |         uint256 claimableAssets = superVault.maxWithdraw(_getActor());
  35 | *   |         assets %= claimableAssets + 1;
  36 |     | 
  37 | *   |         superVault_withdraw(assets);
  38 |     |     }
  39 |     | 
  40 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
  41 |     | 
  42 | *r  |     function superVault_approve(address spender, uint256 value) public asActor {
  43 | *r  |         superVault.approve(spender, value);
  44 |     |     }
  45 |     | 
  46 | *r  |     function superVault_burnShares(uint256 amount) public asActor {
  47 | *   |         superVault.burnShares(amount);
  48 |     |     }
  49 |     | 
  50 |     |     /// @dev Property: pendingRedeemRequest should be 0 after a user calls cancelRedeem
  51 |     |     /// @dev Property: averageRequestPPS should be 0 after a user calls cancelRedeem
  52 |     |     /// @dev Property: user shouldn't receive more than convertToAssets(pendingRedeemRequest) after cancelRedeem
  53 | *r  |     function superVault_cancelRedeem_ASSERTION_CANCEL_REDEEM_NO_OVERPAY()
  54 |     |         public
  55 | *   |         updateGhostsWithOpType(OpType.CANCEL)
  56 | *   |     {
  57 | *   |         uint256 pendingRedeemRequestsBefore = superVault.pendingRedeemRequest(
  58 |     |             0,
  59 | *   |             _getActor()
  60 |     |         );
  61 | *   |         uint256 pendingRedeemRequestsAsAssets = superVault.convertToAssets(
  62 |     |             pendingRedeemRequestsBefore
  63 |     |         );
  64 | *   |         uint256 balanceBefore = MockERC20(superVault.asset()).balanceOf(
  65 | *   |             _getActor()
  66 |     |         );
  67 |     | 
  68 | *   |         vm.prank(_getActor());
  69 | *r  |         superVault.cancelRedeem(_getActor());
  70 |     | 
  71 | *   |         uint256 pendingRedeemRequestsAfter = superVault.pendingRedeemRequest(
  72 |     |             0,
  73 | *   |             _getActor()
  74 |     |         );
  75 | *   |         uint256 averageRequestPPS = superVaultStrategy
  76 | *   |             .getSuperVaultState(_getActor())
  77 |     |             .averageRequestPPS;
  78 | *   |         uint256 balanceAfter = MockERC20(superVault.asset()).balanceOf(
  79 | *   |             _getActor()
  80 |     |         );
  81 |     | 
  82 |     |         // Checks
  83 | *   |         eq(
  84 | *   |             pendingRedeemRequestsAfter,
  85 | *   |             0,
  86 | *   |             ASSERTION_CANCEL_REDEEM_NO_OVERPAY
  87 |     |         );
  88 | *   |         eq(
  89 | *   |             averageRequestPPS,
  90 | *   |             0,
  91 | *   |             ASSERTION_CANCEL_REDEEM_NO_OVERPAY
  92 |     |         );
  93 | *   |         lte(
  94 | *   |             balanceAfter - balanceBefore,
  95 | *   |             pendingRedeemRequestsAsAssets,
  96 | *   |             ASSERTION_CANCEL_REDEEM_NO_OVERPAY
  97 |     |         );
  98 |     |     }
  99 |     | 
 100 |     |     /// @dev Property: previewDeposit returns the correct amounts compared to executing a deposit
 101 | *r  |     function superVault_deposit_ASSERTION_PREVIEW_DEPOSIT_MATCHES_EXECUTION(
 102 |     |         uint256 assets
 103 | *   |     ) public updateGhostsWithOpType(OpType.ADD) {
 104 | *r  |         uint256 previewShares = superVault.previewDeposit(assets);
 105 |     | 
 106 | *   |         vm.prank(_getActor());
 107 | *r  |         uint256 shares = superVault.deposit(assets, _getActor());
 108 |     | 
 109 | *   |         eq(
 110 | *   |             previewShares,
 111 | *   |             shares,
 112 | *   |             ASSERTION_PREVIEW_DEPOSIT_MATCHES_EXECUTION
 113 |     |         );
 114 |     |     }
 115 |     | 
 116 |     |     /// @dev Property: previewMint returns the correct amounts compared to executing a mint
 117 | *r  |     function superVault_mint_ASSERTION_PREVIEW_MINT_MATCHES_EXECUTION(
 118 |     |         uint256 shares
 119 | *   |     ) public updateGhostsWithOpType(OpType.ADD) {
 120 | *r  |         uint256 previewMint = superVault.previewMint(shares);
 121 |     | 
 122 | *   |         vm.prank(_getActor());
 123 | *r  |         uint256 assets = superVault.mint(shares, _getActor());
 124 |     | 
 125 | *   |         eq(
 126 | *   |             assets,
 127 | *   |             previewMint,
 128 | *   |             ASSERTION_PREVIEW_MINT_MATCHES_EXECUTION
 129 |     |         );
 130 |     |     }
 131 |     | 
 132 | *r  |     function superVault_invalidateNonce(bytes32 nonce) public asActor {
 133 | *   |         superVault.invalidateNonce(nonce);
 134 |     |     }
 135 |     | 
 136 | *r  |     function superVault_redeem(
 137 |     |         uint256 shares
 138 | *   |     ) public updateGhostsWithOpType(OpType.REMOVE) asActor {
 139 | *   |         superVault.redeem(shares, _getActor(), _getActor());
 140 |     |     }
 141 |     | 
 142 | *r  |     function superVault_withdraw(
 143 |     |         uint256 assets
 144 | *   |     ) public updateGhostsWithOpType(OpType.REMOVE) asActor {
 145 | *   |         superVault.withdraw(assets, _getActor(), _getActor());
 146 |     |     }
 147 |     | 
 148 | *r  |     function superVault_requestRedeem(
 149 |     |         uint256 shares
 150 | *   |     ) public updateGhostsWithOpType(OpType.REQUEST) asActor {
 151 | *r  |         superVault.requestRedeem(shares, _getActor(), _getActor());
 152 |     |     }
 153 |     | 
 154 | *r  |     function superVault_setOperator(
 155 |     |         uint256 entropy,
 156 |     |         bool approved
 157 |     |     ) public asActor {
 158 | *   |         address operator = _getRandomActor(entropy);
 159 | *r  |         superVault.setOperator(operator, approved);
 160 |     |     }
 161 |     | 
 162 |     |     /// @dev Propery: _update should never revert
 163 |     |     /// @dev Property: Transfers of shares should transfer the exact amount of accumulatorShares to the recipient
 164 |     |     /// @dev Property: Transfers of shares should transfer the exact amount of accumulatorCostBasis to the recipient
 165 |     |     // NOTE: _update only gets called on transfer of Vault shares
 166 | *r  |     function superVault_transfer_ASSERTION_TRANSFER_SHARES_CONSERVED(
 167 |     |         uint256 entropy,
 168 |     |         uint256 value
 169 | *   |     ) public updateGhostsWithOpType(OpType.TRANSFER) {
 170 | *   |         address to = _getRandomActor(entropy);
 171 | *   |         ISuperVaultStrategy.SuperVaultState
 172 | *   |             memory stateSenderBefore = superVaultStrategy.getSuperVaultState(
 173 | *   |                 _getActor()
 174 |     |             );
 175 | *   |         ISuperVaultStrategy.SuperVaultState
 176 | *   |             memory stateRecipientBefore = superVaultStrategy.getSuperVaultState(
 177 |     |                 to
 178 |     |             );
 179 |     | 
 180 | *   |         vm.prank(_getActor());
 181 | *   |         try superVault.transfer(to, value) {
 182 | *   |             ISuperVaultStrategy.SuperVaultState
 183 | *   |                 memory stateSenderAfter = superVaultStrategy.getSuperVaultState(
 184 | *   |                     _getActor()
 185 |     |                 );
 186 | *   |             ISuperVaultStrategy.SuperVaultState
 187 | *   |                 memory stateRecipientAfter = superVaultStrategy
 188 |     |                     .getSuperVaultState(to);
 189 |     | 
 190 | *   |             eq(
 191 | *   |                 stateSenderBefore.accumulatorShares -
 192 | *   |                     stateSenderAfter.accumulatorShares,
 193 | *   |                 stateRecipientAfter.accumulatorShares -
 194 | *   |                     stateRecipientBefore.accumulatorShares,
 195 | *   |                 ASSERTION_TRANSFER_SHARES_CONSERVED
 196 |     |             );
 197 | *   |             eq(
 198 | *   |                 stateSenderBefore.accumulatorCostBasis -
 199 | *   |                     stateSenderAfter.accumulatorCostBasis,
 200 | *   |                 stateRecipientAfter.accumulatorCostBasis -
 201 | *   |                     stateRecipientBefore.accumulatorCostBasis,
 202 |     |                 ASSERTION_TRANSFER_SHARES_CONSERVED
 203 |     |             );
 204 | *   |         } catch (bytes memory err) {
 205 | *   |             bool expectedError;
 206 | *   |             expectedError = checkError(
 207 | *   |                 err,
 208 |     |                 "ERC20InsufficientBalance(address,uint256,uint256)"
 209 |     |             );
 210 | *   |             t(expectedError, ASSERTION_TRANSFER_SHARES_CONSERVED);
 211 |     |         }
 212 |     |     }
 213 |     | 
 214 |     |     /// @dev Propery: _update should never revert
 215 |     |     // NOTE: _update only gets called on transfer of Vault shares
 216 | *r  |     function superVault_transferFrom_ASSERTION_UPDATE_SHOULD_NOT_REVERT_TRANSFER_FROM(
 217 |     |         uint256 entropyFrom,
 218 |     |         uint256 entropyTo,
 219 |     |         uint256 value
 220 | *   |     ) public updateGhostsWithOpType(OpType.TRANSFER) {
 221 | *   |         address from = _getRandomActor(entropyFrom);
 222 | *   |         address to = _getRandomActor(entropyTo);
 223 |     | 
 224 | *   |         vm.prank(_getActor());
 225 | *   |         try superVault.transferFrom(from, to, value) {} catch (
 226 |     |             bytes memory err
 227 | *   |         ) {
 228 | *   |             bool expectedError;
 229 | *   |             expectedError =
 230 | *   |                 checkError(
 231 | *   |                     err,
 232 |     |                     "ERC20InsufficientBalance(address,uint256,uint256)"
 233 |     |                 ) ||
 234 | *   |                 checkError(
 235 | *   |                     err,
 236 |     |                     "ERC20InsufficientAllowance(address,uint256,uint256)"
 237 |     |                 );
 238 | *   |             t(
 239 | *   |                 expectedError,
 240 | *   |                 ASSERTION_UPDATE_SHOULD_NOT_REVERT_TRANSFER_FROM
 241 |     |             );
 242 |     |         }
 243 |     |     }
 244 |     | 
 245 |     |     /// @dev removed because signature components not fuzzable
 246 |     |     // function superVault_authorizeOperator(
 247 |     |     //     address controller,
 248 |     |     //     address operator,
 249 |     |     //     bool approved,
 250 |     |     //     bytes32 nonce,
 251 |     |     //     uint256 deadline,
 252 |     |     //     bytes memory signature
 253 |     |     // ) public asActor {
 254 |     |     //     superVault.authorizeOperator(
 255 |     |     //         controller,
 256 |     |     //         operator,
 257 |     |     //         approved,
 258 |     |     //         nonce,
 259 |     |     //         deadline,
 260 |     |     //         signature
 261 |     |     //     );
 262 |     |     // }
 263 |     | }
 264 |     | 

/opt/scfuzzbench/work/target/test/recon/targets/YieldSourceTargets.sol
   1 |     | // SPDX-License-Identifier: GPL-2.0
   2 |     | pragma solidity ^0.8.0;
   3 |     | 
   4 |     | // Chimera deps
   5 |     | import {BaseTargetFunctions} from "@chimera/BaseTargetFunctions.sol";
   6 |     | import {vm} from "@chimera/Hevm.sol";
   7 |     | 
   8 |     | // Helpers
   9 |     | import {Panic} from "@recon/Panic.sol";
  10 |     | 
  11 |     | import {Properties} from "../Properties.sol";
  12 |     | import {MockERC4626Tester, FunctionType, RevertType} from "../mocks/MockERC4626Tester.sol";
  13 |     | import {MockERC5115Tester, RevertType as RevertType5115} from "../mocks/MockERC5115Tester.sol";
  14 |     | import {MockERC7540Tester} from "../mocks/MockERC7540Tester.sol";
  15 |     | import {YieldSourceType} from "../managers/YieldManager.sol";
  16 |     | 
  17 |     | /// @dev Target functions for yield source testers which are used as yield sources in SuperVaultStrategy
  18 |     | abstract contract YieldSourceTargets is BaseTargetFunctions, Properties {
  19 |     |     /// AUTO GENERATED TARGET FUNCTIONS - WARNING: DO NOT DELETE OR MODIFY THIS LINE ///
  20 |     | 
  21 |     |     /// ERC20 functions (available across all types as they inherit from MockERC20) ///
  22 | *r  |     function yieldSource_approve(
  23 |     |         address spender,
  24 |     |         uint256 value
  25 |     |     ) public asActor {
  26 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
  27 | *   |         address yieldSource = _getYieldSource();
  28 |     | 
  29 | *   |         if (currentType == YieldSourceType.ERC4626) {
  30 | *   |             MockERC4626Tester(yieldSource).approve(spender, value);
  31 | *   |         } else if (currentType == YieldSourceType.ERC5115) {
  32 |     |             MockERC5115Tester(yieldSource).approve(spender, value);
  33 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
  34 | *   |             MockERC7540Tester(yieldSource).approve(spender, value);
  35 |     |         }
  36 |     |     }
  37 |     | 
  38 | *r  |     function yieldSource_setDecimalsOffset(
  39 |     |         uint8 targetDecimalsOffset
  40 | *   |     ) public asActor {
  41 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
  42 | *   |         address yieldSource = _getYieldSource();
  43 |     | 
  44 | *   |         if (currentType == YieldSourceType.ERC4626) {
  45 | *   |             MockERC4626Tester(yieldSource).setDecimalsOffset(
  46 |     |                 targetDecimalsOffset
  47 |     |             );
  48 |     |         }
  49 |     |         // Note: ERC5115 and ERC7540 don't have setDecimalsOffset function
  50 |     |     }
  51 |     | 
  52 | *r  |     function yieldSource_transfer(address to, uint256 value) public asActor {
  53 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
  54 | *   |         address yieldSource = _getYieldSource();
  55 |     | 
  56 | *   |         if (currentType == YieldSourceType.ERC4626) {
  57 | *r  |             MockERC4626Tester(yieldSource).transfer(to, value);
  58 | *   |         } else if (currentType == YieldSourceType.ERC5115) {
  59 |     |             MockERC5115Tester(yieldSource).transfer(to, value);
  60 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
  61 | *r  |             MockERC7540Tester(yieldSource).transfer(to, value);
  62 |     |         }
  63 |     |     }
  64 |     | 
  65 | *r  |     function yieldSource_transferFrom(
  66 |     |         address from,
  67 |     |         address to,
  68 |     |         uint256 value
  69 |     |     ) public asActor {
  70 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
  71 | *   |         address yieldSource = _getYieldSource();
  72 |     | 
  73 | *   |         if (currentType == YieldSourceType.ERC4626) {
  74 | *r  |             MockERC4626Tester(yieldSource).transferFrom(from, to, value);
  75 | *   |         } else if (currentType == YieldSourceType.ERC5115) {
  76 |     |             MockERC5115Tester(yieldSource).transferFrom(from, to, value);
  77 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
  78 | *r  |             MockERC7540Tester(yieldSource).transferFrom(from, to, value);
  79 |     |         }
  80 |     |     }
  81 |     | 
  82 |     |     /// Core Vault Functions (ERC4626/ERC4626-like) ///
  83 | *r  |     function yieldSource_deposit(
  84 |     |         uint256 assets,
  85 |     |         address receiver
  86 |     |     ) public asActor {
  87 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
  88 | *   |         address yieldSource = _getYieldSource();
  89 |     | 
  90 | *   |         if (currentType == YieldSourceType.ERC4626) {
  91 | *   |             MockERC4626Tester(yieldSource).deposit(assets, receiver);
  92 |     |         }
  93 |     |         // Note: ERC5115 has different deposit signature, handled separately
  94 |     |         // Note: ERC7540 has different deposit signature, handled separately
  95 |     |     }
  96 |     | 
  97 | *r  |     function yieldSource_mint(uint256 shares, address receiver) public asActor {
  98 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
  99 | *   |         address yieldSource = _getYieldSource();
 100 |     | 
 101 | *   |         if (currentType == YieldSourceType.ERC4626) {
 102 | *r  |             MockERC4626Tester(yieldSource).mint(shares, receiver);
 103 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
 104 | *r  |             MockERC7540Tester(yieldSource).mint(shares, receiver);
 105 |     |         }
 106 |     |         // Note: ERC5115 doesn't have mint function
 107 |     |     }
 108 |     | 
 109 | *r  |     function yieldSource_withdraw(
 110 |     |         uint256 assets,
 111 |     |         address receiver,
 112 |     |         address owner
 113 |     |     ) public asActor {
 114 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 115 | *   |         address yieldSource = _getYieldSource();
 116 |     | 
 117 | *   |         if (currentType == YieldSourceType.ERC4626) {
 118 | *r  |             MockERC4626Tester(yieldSource).withdraw(assets, receiver, owner);
 119 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
 120 | *   |             MockERC7540Tester(yieldSource).withdraw(assets, receiver, owner);
 121 |     |         }
 122 |     |         // Note: ERC5115 doesn't have withdraw function
 123 |     |     }
 124 |     | 
 125 | *r  |     function yieldSource_redeem(
 126 |     |         uint256 shares,
 127 |     |         address receiver,
 128 |     |         address owner
 129 |     |     ) public asActor {
 130 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 131 | *   |         address yieldSource = _getYieldSource();
 132 |     | 
 133 | *   |         if (currentType == YieldSourceType.ERC4626) {
 134 | *   |             MockERC4626Tester(yieldSource).redeem(shares, receiver, owner);
 135 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
 136 | *   |             MockERC7540Tester(yieldSource).redeem(shares, receiver, owner);
 137 |     |         }
 138 |     |         // Note: ERC5115 has different redeem signature, handled separately
 139 |     |     }
 140 |     | 
 141 |     |     /// ERC5115-specific functions ///
 142 | *r  |     function yieldSource_deposit5115(
 143 |     |         address receiver,
 144 |     |         address tokenIn,
 145 |     |         uint256 amountTokenToDeposit,
 146 |     |         uint256 minSharesOut,
 147 |     |         bool depositFromInternalBalance
 148 |     |     ) public asActor {
 149 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 150 | *   |         address yieldSource = _getYieldSource();
 151 |     | 
 152 | *   |         if (currentType == YieldSourceType.ERC5115) {
 153 |     |             MockERC5115Tester(yieldSource).deposit(
 154 |     |                 receiver,
 155 |     |                 tokenIn,
 156 |     |                 amountTokenToDeposit,
 157 |     |                 minSharesOut,
 158 |     |                 depositFromInternalBalance
 159 |     |             );
 160 |     |         }
 161 |     |     }
 162 |     | 
 163 | *r  |     function yieldSource_redeem5115(
 164 |     |         address receiver,
 165 |     |         uint256 amountSharesToRedeem,
 166 |     |         address tokenOut,
 167 |     |         uint256 minTokenOut,
 168 |     |         bool burnFromInternalBalance
 169 |     |     ) public asActor {
 170 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 171 | *   |         address yieldSource = _getYieldSource();
 172 |     | 
 173 | *   |         if (currentType == YieldSourceType.ERC5115) {
 174 |     |             MockERC5115Tester(yieldSource).redeem(
 175 |     |                 receiver,
 176 |     |                 amountSharesToRedeem,
 177 |     |                 tokenOut,
 178 |     |                 minTokenOut,
 179 |     |                 burnFromInternalBalance
 180 |     |             );
 181 |     |         }
 182 |     |     }
 183 |     | 
 184 |     |     /// ERC7540-specific functions ///
 185 | *r  |     function yieldSource_setOperator(
 186 |     |         address operator,
 187 |     |         bool approved
 188 |     |     ) public asActor {
 189 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 190 | *   |         address yieldSource = _getYieldSource();
 191 |     | 
 192 | *   |         if (currentType == YieldSourceType.ERC7540) {
 193 | *   |             MockERC7540Tester(yieldSource).setOperator(operator, approved);
 194 |     |         }
 195 |     |     }
 196 |     | 
 197 | *r  |     function yieldSource_requestDeposit(
 198 |     |         uint256 assets,
 199 |     |         address controller,
 200 |     |         address owner
 201 |     |     ) public asActor {
 202 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 203 | *   |         address yieldSource = _getYieldSource();
 204 |     | 
 205 | *   |         if (currentType == YieldSourceType.ERC7540) {
 206 | *   |             MockERC7540Tester(yieldSource).requestDeposit(
 207 | *   |                 assets,
 208 | *   |                 controller,
 209 | *   |                 owner
 210 |     |             );
 211 |     |         }
 212 |     |     }
 213 |     | 
 214 | *r  |     function yieldSource_requestRedeem(
 215 |     |         uint256 shares,
 216 |     |         address controller,
 217 |     |         address owner
 218 |     |     ) public asActor {
 219 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 220 | *   |         address yieldSource = _getYieldSource();
 221 |     | 
 222 | *   |         if (currentType == YieldSourceType.ERC7540) {
 223 | *   |             MockERC7540Tester(yieldSource).requestRedeem(
 224 | *   |                 shares,
 225 | *   |                 controller,
 226 | *   |                 owner
 227 |     |             );
 228 |     |         }
 229 |     |     }
 230 |     | 
 231 | *r  |     function yieldSource_cancelDepositRequest(
 232 |     |         uint256 requestId,
 233 |     |         address controller
 234 |     |     ) public asActor {
 235 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 236 | *   |         address yieldSource = _getYieldSource();
 237 |     | 
 238 | *   |         if (currentType == YieldSourceType.ERC7540) {
 239 | *   |             MockERC7540Tester(yieldSource).cancelDepositRequest(
 240 | *   |                 requestId,
 241 | *   |                 controller
 242 |     |             );
 243 |     |         }
 244 |     |     }
 245 |     | 
 246 | *r  |     function yieldSource_cancelRedeemRequest(
 247 |     |         uint256 requestId,
 248 |     |         address controller
 249 |     |     ) public asActor {
 250 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 251 | *   |         address yieldSource = _getYieldSource();
 252 |     | 
 253 | *   |         if (currentType == YieldSourceType.ERC7540) {
 254 | *   |             MockERC7540Tester(yieldSource).cancelRedeemRequest(
 255 | *   |                 requestId,
 256 | *   |                 controller
 257 |     |             );
 258 |     |         }
 259 |     |     }
 260 |     | 
 261 | *r  |     function yieldSource_claimCancelDepositRequest(
 262 |     |         uint256 requestId,
 263 |     |         address receiver,
 264 |     |         address controller
 265 |     |     ) public asActor {
 266 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 267 | *   |         address yieldSource = _getYieldSource();
 268 |     | 
 269 | *   |         if (currentType == YieldSourceType.ERC7540) {
 270 | *   |             MockERC7540Tester(yieldSource).claimCancelDepositRequest(
 271 | *   |                 requestId,
 272 | *   |                 receiver,
 273 | *   |                 controller
 274 |     |             );
 275 |     |         }
 276 |     |     }
 277 |     | 
 278 | *r  |     function yieldSource_claimCancelRedeemRequest(
 279 |     |         uint256 requestId,
 280 |     |         address receiver,
 281 |     |         address controller
 282 |     |     ) public asActor {
 283 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 284 | *   |         address yieldSource = _getYieldSource();
 285 |     | 
 286 | *   |         if (currentType == YieldSourceType.ERC7540) {
 287 | *r  |             MockERC7540Tester(yieldSource).claimCancelRedeemRequest(
 288 | *   |                 requestId,
 289 | *   |                 receiver,
 290 | *   |                 controller
 291 |     |             );
 292 |     |         }
 293 |     |     }
 294 |     | 
 295 | *r  |     function yieldSource_deposit7540(
 296 |     |         uint256 assets,
 297 |     |         address receiver,
 298 |     |         address controller
 299 |     |     ) public asActor {
 300 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 301 | *   |         address yieldSource = _getYieldSource();
 302 |     | 
 303 | *   |         if (currentType == YieldSourceType.ERC7540) {
 304 | *   |             MockERC7540Tester(yieldSource).deposit(
 305 | *   |                 assets,
 306 | *   |                 receiver,
 307 | *   |                 controller
 308 |     |             );
 309 |     |         }
 310 |     |     }
 311 |     | 
 312 |     |     /// Testing-specific functions (ERC4626 only) ///
 313 | *r  |     function yieldSource_setRevertBehavior4626(
 314 |     |         uint8 functionType,
 315 |     |         uint8 revertType
 316 |     |     ) public asActor {
 317 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 318 | *   |         address yieldSource = _getYieldSource();
 319 |     | 
 320 | *   |         if (currentType == YieldSourceType.ERC4626) {
 321 | *   |             MockERC4626Tester(yieldSource).setRevertBehavior(
 322 | *   |                 FunctionType(functionType),
 323 | *   |                 RevertType(revertType)
 324 |     |             );
 325 |     |         }
 326 |     |     }
 327 |     | 
 328 |     |     /// Testing-specific functions (ERC5115 only) ///
 329 | *r  |     function yieldSource_setRevertBehavior5115(
 330 |     |         uint8 revertType
 331 |     |     ) public asActor {
 332 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 333 | *   |         address yieldSource = _getYieldSource();
 334 |     | 
 335 | *   |         if (currentType == YieldSourceType.ERC5115) {
 336 |     |             MockERC5115Tester(yieldSource).setRevertBehavior(
 337 |     |                 RevertType5115(revertType)
 338 |     |             );
 339 |     |         }
 340 |     |     }
 341 |     | 
 342 |     |     /// Common yield manipulation functions ///
 343 |     | 
 344 | *r  |     function yieldSource_simulateLoss(uint256 lossAmount) public {
 345 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 346 | *   |         address yieldSource = _getYieldSource();
 347 |     | 
 348 | *   |         if (currentType == YieldSourceType.ERC4626) {
 349 | *   |             MockERC4626Tester(yieldSource).simulateLoss(lossAmount);
 350 | *   |         } else if (currentType == YieldSourceType.ERC5115) {
 351 |     |             MockERC5115Tester(yieldSource).simulateLoss(lossAmount);
 352 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
 353 | *   |             MockERC7540Tester(yieldSource).simulateLoss(lossAmount);
 354 |     |         }
 355 |     |     }
 356 |     | 
 357 | *r  |     function yieldSource_simulateGain(uint256 gainAmount) public {
 358 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 359 | *   |         address yieldSource = _getYieldSource();
 360 |     | 
 361 | *   |         if (currentType == YieldSourceType.ERC4626) {
 362 | *   |             MockERC4626Tester(yieldSource).simulateGain(gainAmount);
 363 | *   |         } else if (currentType == YieldSourceType.ERC5115) {
 364 |     |             MockERC5115Tester(yieldSource).simulateGain(gainAmount);
 365 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
 366 | *   |             MockERC7540Tester(yieldSource).simulateGain(gainAmount);
 367 |     |         }
 368 |     |     }
 369 |     | 
 370 | *r  |     function yieldSource_setLossOnWithdraw(
 371 |     |         uint256 lossOnWithdraw
 372 |     |     ) public asActor {
 373 | *   |         YieldSourceType currentType = _getCurrentYieldSourceType();
 374 | *   |         address yieldSource = _getYieldSource();
 375 |     | 
 376 | *   |         if (currentType == YieldSourceType.ERC4626) {
 377 | *   |             MockERC4626Tester(yieldSource).setLossOnWithdraw(lossOnWithdraw);
 378 | *   |         } else if (currentType == YieldSourceType.ERC5115) {
 379 |     |             MockERC5115Tester(yieldSource).setLossOnWithdraw(lossOnWithdraw);
 380 | *   |         } else if (currentType == YieldSourceType.ERC7540) {
 381 | *   |             MockERC7540Tester(yieldSource).setLossOnWithdraw(lossOnWithdraw);
 382 |     |         }
 383 |     |     }
 384 |     | 
 385 |     |     /// Yield source management functions ///
 386 | *r  |     function yieldSource_switchToERC4626() public {
 387 | *   |         _switchYieldSource(0); // Switch to first yield source (ERC4626)
 388 |     |     }
 389 |     | 
 390 | *r  |     function yieldSource_switchToERC5115() public {
 391 | *   |         _switchYieldSource(1); // Switch to second yield source (ERC5115)
 392 |     |     }
 393 |     | 
 394 | *r  |     function yieldSource_switchToERC7540() public {
 395 | *   |         _switchYieldSource(2); // Switch to third yield source (ERC7540)
 396 |     |     }
 397 |     | 
 398 | *r  |     function yieldSource_switchRandom(uint256 entropy) public {
 399 |     |         // Randomly switch between the three deployed yield sources
 400 | *   |         _switchYieldSource(entropy);
 401 |     |     }
 402 |     | }
 403 |     | 

