From 91513462cc7981ef98daaede0059a22f71090c16 Mon Sep 17 00:00:00 2001 From: Filip Malachowicz Date: Fri, 28 Nov 2025 10:59:58 +0100 Subject: [PATCH 1/3] feat: VIP to enable flashloans to LeverageStrategiesManager contract on bscmainnet --- simulations/vip-575/abi/FlashLoanFacet.json | 1218 +++++++++++++++++ .../abi/LeverageStrategiesManager.json | 805 +++++++++++ simulations/vip-575/bscmainnet.ts | 76 + vips/vip-575/bscmainnet.ts | 45 + 4 files changed, 2144 insertions(+) create mode 100644 simulations/vip-575/abi/FlashLoanFacet.json create mode 100644 simulations/vip-575/abi/LeverageStrategiesManager.json create mode 100644 simulations/vip-575/bscmainnet.ts create mode 100644 vips/vip-575/bscmainnet.ts diff --git a/simulations/vip-575/abi/FlashLoanFacet.json b/simulations/vip-575/abi/FlashLoanFacet.json new file mode 100644 index 000000000..2adc7e8fa --- /dev/null +++ b/simulations/vip-575/abi/FlashLoanFacet.json @@ -0,0 +1,1218 @@ +[ + { + "inputs": [], + "name": "AlreadyInSelectedPool", + "type": "error" + }, + { + "inputs": [], + "name": "ArrayLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowNotAllowedInPool", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyPoolLabel", + "type": "error" + }, + { + "inputs": [], + "name": "ExecuteFlashLoanFailed", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToCreateDebtPosition", + "type": "error" + }, + { + "inputs": [], + "name": "FlashLoanNotEnabled", + "type": "error" + }, + { + "inputs": [], + "name": "FlashLoanPausedSystemWide", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "InactivePool", + "type": "error" + }, + { + "inputs": [], + "name": "IncompatibleBorrowedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFlashLoanParams", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOperationForCorePool", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum WeightFunction", + "name": "strategy", + "type": "uint8" + } + ], + "name": "InvalidWeightingStrategy", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "name": "LiquidityCheckFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketAlreadyListed", + "type": "error" + }, + { + "inputs": [], + "name": "MarketConfigNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketNotListed", + "type": "error" + }, + { + "inputs": [], + "name": "MarketNotListedInCorePool", + "type": "error" + }, + { + "inputs": [], + "name": "NoAssetsRequested", + "type": "error" + }, + { + "inputs": [], + "name": "NotAnApprovedDelegate", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "required", + "type": "uint256" + } + ], + "name": "NotEnoughRepayment", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "PoolDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PoolMarketNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotAuthorizedForFlashLoan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximum", + "type": "uint256" + } + ], + "name": "TooManyAssetsRequested", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributedVAIVaultVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract VToken[]", + "name": "assets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "FlashLoanExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "onBehalf", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repaidAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingDebt", + "type": "uint256" + } + ], + "name": "FlashLoanRepaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "bool", + "name": "isWhitelisted", + "type": "bool" + } + ], + "name": "IsAccountFlashLoanWhitelisted", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_FLASHLOAN_ASSETS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum Action", + "name": "action", + "type": "uint8" + } + ], + "name": "actionPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "authorizedFlashLoan", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "corePoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "onBehalf", + "type": "address" + }, + { + "internalType": "address payable", + "name": "receiver", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "underlyingAmounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "param", + "type": "bytes" + } + ], + "name": "executeFlashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getPoolMarketIndex", + "outputs": [ + { + "internalType": "PoolMarketId", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getXVSAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabledForUser", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "bool", + "name": "allowCorePoolFallback", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userPoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-575/abi/LeverageStrategiesManager.json b/simulations/vip-575/abi/LeverageStrategiesManager.json new file mode 100644 index 000000000..cb90afd67 --- /dev/null +++ b/simulations/vip-575/abi/LeverageStrategiesManager.json @@ -0,0 +1,805 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "BorrowBehalfFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "err", + "type": "uint256" + } + ], + "name": "EnterMarketFailed", + "type": "error" + }, + { + "inputs": [], + "name": "FlashLoanAssetOrAmountMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "InitiatorMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFundsToRepayFlashloan", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExecuteOperation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "MarketNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "MintBehalfFailed", + "type": "error" + }, + { + "inputs": [], + "name": "NotAnApprovedDelegate", + "type": "error" + }, + { + "inputs": [], + "name": "OnBehalfMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "OperationCausesLiquidation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RedeemBehalfFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "RepayBehalfFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SlippageExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "TokenSwapCallFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedExecutor", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroFlashLoanAmount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DustTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IVToken", + "name": "collateralMarket", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateralAmountSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IVToken", + "name": "borrowedMarket", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowedAmountToFlashLoan", + "type": "uint256" + } + ], + "name": "LeverageEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IVToken", + "name": "collateralMarket", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IVToken", + "name": "borrowedMarket", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowedAmountSeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowedAmountToFlashLoan", + "type": "uint256" + } + ], + "name": "LeverageEnteredFromBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IVToken", + "name": "collateralMarket", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateralAmountToRedeemForSwap", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IVToken", + "name": "borrowedMarket", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowedAmountToFlashLoan", + "type": "uint256" + } + ], + "name": "LeverageExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IVToken", + "name": "collateralMarket", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateralAmountSeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateralAmountToFlashLoan", + "type": "uint256" + } + ], + "name": "SingleAssetLeverageEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IVToken", + "name": "collateralMarket", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateralAmountToFlashLoan", + "type": "uint256" + } + ], + "name": "SingleAssetLeverageExited", + "type": "event" + }, + { + "inputs": [], + "name": "COMPTROLLER", + "outputs": [ + { + "internalType": "contract IComptroller", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVToken", + "name": "_collateralMarket", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_collateralAmountSeed", + "type": "uint256" + }, + { + "internalType": "contract IVToken", + "name": "_borrowedMarket", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_borrowedAmountToFlashLoan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minAmountOutAfterSwap", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_swapData", + "type": "bytes" + } + ], + "name": "enterLeverage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVToken", + "name": "_collateralMarket", + "type": "address" + }, + { + "internalType": "contract IVToken", + "name": "_borrowedMarket", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_borrowedAmountSeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_borrowedAmountToFlashLoan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minAmountOutAfterSwap", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_swapData", + "type": "bytes" + } + ], + "name": "enterLeverageFromBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVToken", + "name": "_collateralMarket", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_collateralAmountSeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_collateralAmountToFlashLoan", + "type": "uint256" + } + ], + "name": "enterSingleAssetLeverage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "premiums", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "initiator", + "type": "address" + }, + { + "internalType": "address", + "name": "onBehalf", + "type": "address" + }, + { + "internalType": "bytes", + "name": "param", + "type": "bytes" + } + ], + "name": "executeOperation", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "repayAmounts", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVToken", + "name": "_collateralMarket", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_collateralAmountToRedeemForSwap", + "type": "uint256" + }, + { + "internalType": "contract IVToken", + "name": "_borrowedMarket", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_borrowedAmountToFlashLoan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minAmountOutAfterSwap", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_swapData", + "type": "bytes" + } + ], + "name": "exitLeverage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVToken", + "name": "_collateralMarket", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_collateralAmountToFlashLoan", + "type": "uint256" + } + ], + "name": "exitSingleAssetLeverage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "contract IProtocolShareReserve", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "swapHelper", + "outputs": [ + { + "internalType": "contract SwapHelper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] diff --git a/simulations/vip-575/bscmainnet.ts b/simulations/vip-575/bscmainnet.ts new file mode 100644 index 000000000..4f77efee0 --- /dev/null +++ b/simulations/vip-575/bscmainnet.ts @@ -0,0 +1,76 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import { LEVERAGE_STRATEGIES_MANAGER, UNITROLLER, vip575 } from "../../vips/vip-575/bscmainnet"; +import COMPTROLLER_ABI from "./abi/FlashLoanFacet.json"; +import LEVERAGE_STRATEGIES_MANAGER_ABI from "./abi/LeverageStrategiesManager.json"; + +const { bscmainnet } = NETWORK_ADDRESSES; + +const PSR = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; +const SWAP_HELPER = "0xe1a3b4189F56Cf38747BE79348b8664Ef18cCFd1"; + +forking(69761773, async () => { + let comptroller: Contract; + let leverageStrategiesManager: Contract; + + before(async () => { + comptroller = await ethers.getContractAt(COMPTROLLER_ABI, UNITROLLER); + leverageStrategiesManager = await ethers.getContractAt( + LEVERAGE_STRATEGIES_MANAGER_ABI, + LEVERAGE_STRATEGIES_MANAGER, + ); + }); + + describe("Pre-VIP behavior", () => { + it("LeverageStrategiesManager should not be whitelisted for flash loans", async () => { + expect(await comptroller.authorizedFlashLoan(LEVERAGE_STRATEGIES_MANAGER)).to.equal(false); + }); + + it("LeverageStrategiesManager should have NORMAL_TIMELOCK as pending owner", async () => { + expect(await leverageStrategiesManager.pendingOwner()).to.equal(bscmainnet.NORMAL_TIMELOCK); + }); + + it("Comptroller should have flash loans unpaused", async () => { + expect(await comptroller.flashLoanPaused()).to.equal(false); + }); + + describe("LeverageStrategiesManager configuration", () => { + it("should have correct COMPTROLLER", async () => { + expect(await leverageStrategiesManager.COMPTROLLER()).to.equal(UNITROLLER); + }); + + it("should have correct protocolShareReserve", async () => { + expect(await leverageStrategiesManager.protocolShareReserve()).to.equal(PSR); + }); + + it("should have correct swapHelper", async () => { + expect(await leverageStrategiesManager.swapHelper()).to.equal(SWAP_HELPER); + }); + }); + }); + + testVip("VIP-575", await vip575(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [COMPTROLLER_ABI], ["IsAccountFlashLoanWhitelisted"], [1]); + }, + }); + + describe("Post-VIP behavior", () => { + it("LeverageStrategiesManager should be whitelisted for flash loans", async () => { + expect(await comptroller.authorizedFlashLoan(LEVERAGE_STRATEGIES_MANAGER)).to.equal(true); + }); + + it("LeverageStrategiesManager should have NORMAL_TIMELOCK as owner", async () => { + expect(await leverageStrategiesManager.owner()).to.equal(bscmainnet.NORMAL_TIMELOCK); + }); + + it("LeverageStrategiesManager should have zero address as pending owner", async () => { + expect(await leverageStrategiesManager.pendingOwner()).to.equal(ethers.constants.AddressZero); + }); + }); +}); diff --git a/vips/vip-575/bscmainnet.ts b/vips/vip-575/bscmainnet.ts new file mode 100644 index 000000000..711a121f0 --- /dev/null +++ b/vips/vip-575/bscmainnet.ts @@ -0,0 +1,45 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +export const UNITROLLER = "0xfD36E2c2a6789Db23113685031d7F16329158384"; +export const LEVERAGE_STRATEGIES_MANAGER = "0x3Ee4F1474A1071c5fAC97bd881eabcA2Cf8F6085"; + +export const vip575 = () => { + const meta = { + version: "v2", + title: "VIP-575 [BNB Chain] Whitelist LeverageStrategiesManager for flash loans", + description: `#### Summary + +This VIP whitelists the LeverageStrategiesManager contract for flash loans on BNB Chain mainnet. + +#### Description + +This VIP will whitelist the [LeverageStrategiesManager](https://bscscan.com/address/0x3Ee4F1474A1071c5fAC97bd881eabcA2Cf8F6085) contract to enable flash loan functionality for leverage strategies. + +#### Deployed contracts + +- [LeverageStrategiesManager](https://bscscan.com/address/0x3Ee4F1474A1071c5fAC97bd881eabcA2Cf8F6085)`, + forDescription: "Execute", + againstDescription: "Do not execute", + abstainDescription: "Abstain", + }; + + return makeProposal( + [ + { + target: LEVERAGE_STRATEGIES_MANAGER, + signature: "acceptOwnership()", + params: [], + }, + { + target: UNITROLLER, + signature: "setWhiteListFlashLoanAccount(address,bool)", + params: [LEVERAGE_STRATEGIES_MANAGER, true], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip575; From 68fee557f3380dadfae4405857d0d54deead27db Mon Sep 17 00:00:00 2001 From: Filip Malachowicz Date: Thu, 11 Dec 2025 11:46:12 +0100 Subject: [PATCH 2/3] feat: add SwapHelper ownership transfer. use up to date addresses. --- .../abi/LeverageStrategiesManager.json | 55 ++- simulations/vip-575/abi/SwapHelper.json | 444 ++++++++++++++++++ simulations/vip-575/bscmainnet.ts | 33 +- vips/vip-575/bscmainnet.ts | 18 +- 4 files changed, 523 insertions(+), 27 deletions(-) create mode 100644 simulations/vip-575/abi/SwapHelper.json diff --git a/simulations/vip-575/abi/LeverageStrategiesManager.json b/simulations/vip-575/abi/LeverageStrategiesManager.json index cb90afd67..580a65918 100644 --- a/simulations/vip-575/abi/LeverageStrategiesManager.json +++ b/simulations/vip-575/abi/LeverageStrategiesManager.json @@ -109,6 +109,17 @@ "stateMutability": "payable", "type": "receive" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "AccrueInterestFailed", + "type": "error" + }, { "inputs": [ { @@ -136,6 +147,11 @@ "name": "FlashLoanAssetOrAmountMismatch", "type": "error" }, + { + "inputs": [], + "name": "IdenticalMarkets", + "type": "error" + }, { "inputs": [], "name": "InitiatorMismatch", @@ -184,7 +200,13 @@ "type": "error" }, { - "inputs": [], + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], "name": "OperationCausesLiquidation", "type": "error" }, @@ -225,6 +247,11 @@ "name": "UnauthorizedExecutor", "type": "error" }, + { + "inputs": [], + "name": "VBNBNotSupported", + "type": "error" + }, { "inputs": [], "name": "ZeroAddress", @@ -735,19 +762,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "protocolShareReserve", - "outputs": [ - { - "internalType": "contract IProtocolShareReserve", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "renounceOwnership", @@ -781,6 +795,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "vBNB", + "outputs": [ + { + "internalType": "contract IVToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/simulations/vip-575/abi/SwapHelper.json b/simulations/vip-575/abi/SwapHelper.json new file mode 100644 index 000000000..fb92e0573 --- /dev/null +++ b/simulations/vip-575/abi/SwapHelper.json @@ -0,0 +1,444 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "backendSigner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotAuthorized", + "type": "error" + }, + { + "inputs": [], + "name": "DeadlineReached", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [], + "name": "MissingSignature", + "type": "error" + }, + { + "inputs": [], + "name": "NoCallsProvided", + "type": "error" + }, + { + "inputs": [], + "name": "SaltAlreadyUsed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ApprovedMax", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldSigner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newSigner", + "type": "address" + } + ], + "name": "BackendSignerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "GenericCallExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "callsCount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "MulticallExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Swept", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "approveMax", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "backendSigner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "genericCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "calls", + "type": "bytes[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "multicall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newSigner", + "type": "address" + } + ], + "name": "setBackendSigner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "sweep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "usedSalts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-575/bscmainnet.ts b/simulations/vip-575/bscmainnet.ts index 4f77efee0..5ef311fee 100644 --- a/simulations/vip-575/bscmainnet.ts +++ b/simulations/vip-575/bscmainnet.ts @@ -5,18 +5,17 @@ import { NETWORK_ADDRESSES } from "src/networkAddresses"; import { expectEvents } from "src/utils"; import { forking, testVip } from "src/vip-framework"; -import { LEVERAGE_STRATEGIES_MANAGER, UNITROLLER, vip575 } from "../../vips/vip-575/bscmainnet"; +import { LEVERAGE_STRATEGIES_MANAGER, SWAP_HELPER, UNITROLLER, vip575 } from "../../vips/vip-575/bscmainnet"; import COMPTROLLER_ABI from "./abi/FlashLoanFacet.json"; import LEVERAGE_STRATEGIES_MANAGER_ABI from "./abi/LeverageStrategiesManager.json"; +import SWAP_HELPER_ABI from "./abi/SwapHelper.json"; const { bscmainnet } = NETWORK_ADDRESSES; -const PSR = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; -const SWAP_HELPER = "0xe1a3b4189F56Cf38747BE79348b8664Ef18cCFd1"; - -forking(69761773, async () => { +forking(71263393, async () => { let comptroller: Contract; let leverageStrategiesManager: Contract; + let swapHelper: Contract; before(async () => { comptroller = await ethers.getContractAt(COMPTROLLER_ABI, UNITROLLER); @@ -24,6 +23,7 @@ forking(69761773, async () => { LEVERAGE_STRATEGIES_MANAGER_ABI, LEVERAGE_STRATEGIES_MANAGER, ); + swapHelper = await ethers.getContractAt(SWAP_HELPER_ABI, SWAP_HELPER); }); describe("Pre-VIP behavior", () => { @@ -35,6 +35,10 @@ forking(69761773, async () => { expect(await leverageStrategiesManager.pendingOwner()).to.equal(bscmainnet.NORMAL_TIMELOCK); }); + it("SwapHelper should have NORMAL_TIMELOCK as pending owner", async () => { + expect(await swapHelper.pendingOwner()).to.equal(bscmainnet.NORMAL_TIMELOCK); + }); + it("Comptroller should have flash loans unpaused", async () => { expect(await comptroller.flashLoanPaused()).to.equal(false); }); @@ -44,10 +48,6 @@ forking(69761773, async () => { expect(await leverageStrategiesManager.COMPTROLLER()).to.equal(UNITROLLER); }); - it("should have correct protocolShareReserve", async () => { - expect(await leverageStrategiesManager.protocolShareReserve()).to.equal(PSR); - }); - it("should have correct swapHelper", async () => { expect(await leverageStrategiesManager.swapHelper()).to.equal(SWAP_HELPER); }); @@ -72,5 +72,20 @@ forking(69761773, async () => { it("LeverageStrategiesManager should have zero address as pending owner", async () => { expect(await leverageStrategiesManager.pendingOwner()).to.equal(ethers.constants.AddressZero); }); + + it("SwapHelper should have NORMAL_TIMELOCK as owner", async () => { + expect(await swapHelper.owner()).to.equal(bscmainnet.NORMAL_TIMELOCK); + }); + + it("SwapHelper should have zero address as pending owner", async () => { + expect(await swapHelper.pendingOwner()).to.equal(ethers.constants.AddressZero); + }); + + describe("SwapHelper configuration", () => { + it("should have correct backendSigner", async () => { + const backendSigner = await swapHelper.backendSigner(); + expect(backendSigner).to.not.equal(ethers.constants.AddressZero); + }); + }); }); }); diff --git a/vips/vip-575/bscmainnet.ts b/vips/vip-575/bscmainnet.ts index 711a121f0..32a11ff22 100644 --- a/vips/vip-575/bscmainnet.ts +++ b/vips/vip-575/bscmainnet.ts @@ -2,7 +2,8 @@ import { ProposalType } from "src/types"; import { makeProposal } from "src/utils"; export const UNITROLLER = "0xfD36E2c2a6789Db23113685031d7F16329158384"; -export const LEVERAGE_STRATEGIES_MANAGER = "0x3Ee4F1474A1071c5fAC97bd881eabcA2Cf8F6085"; +export const LEVERAGE_STRATEGIES_MANAGER = "0x03F079E809185a669Ca188676D0ADb09cbAd6dC1"; +export const SWAP_HELPER = "0xD79be25aEe798Aa34A9Ba1230003d7499be29A24"; export const vip575 = () => { const meta = { @@ -10,15 +11,19 @@ export const vip575 = () => { title: "VIP-575 [BNB Chain] Whitelist LeverageStrategiesManager for flash loans", description: `#### Summary -This VIP whitelists the LeverageStrategiesManager contract for flash loans on BNB Chain mainnet. +This VIP whitelists the LeverageStrategiesManager contract for flash loans on BNB Chain mainnet and accepts ownership of SwapHelper and LeverageStrategiesManager contracts. #### Description -This VIP will whitelist the [LeverageStrategiesManager](https://bscscan.com/address/0x3Ee4F1474A1071c5fAC97bd881eabcA2Cf8F6085) contract to enable flash loan functionality for leverage strategies. +This VIP will: +- Accept ownership of [SwapHelper](https://bscscan.com/address/0xD79be25aEe798Aa34A9Ba1230003d7499be29A24) contract +- Accept ownership of [LeverageStrategiesManager](https://bscscan.com/address/0x03F079E809185a669Ca188676D0ADb09cbAd6dC1) contract +- Whitelist the [LeverageStrategiesManager](https://bscscan.com/address/0x03F079E809185a669Ca188676D0ADb09cbAd6dC1) contract to enable flash loan functionality for leverage strategies #### Deployed contracts -- [LeverageStrategiesManager](https://bscscan.com/address/0x3Ee4F1474A1071c5fAC97bd881eabcA2Cf8F6085)`, +- [LeverageStrategiesManager](https://bscscan.com/address/0x03F079E809185a669Ca188676D0ADb09cbAd6dC1) +- [SwapHelper](https://bscscan.com/address/0xD79be25aEe798Aa34A9Ba1230003d7499be29A24)`, forDescription: "Execute", againstDescription: "Do not execute", abstainDescription: "Abstain", @@ -26,6 +31,11 @@ This VIP will whitelist the [LeverageStrategiesManager](https://bscscan.com/addr return makeProposal( [ + { + target: SWAP_HELPER, + signature: "acceptOwnership()", + params: [], + }, { target: LEVERAGE_STRATEGIES_MANAGER, signature: "acceptOwnership()", From 9f1957429d905400ab9bf3f7f4205c8a9028fdd9 Mon Sep 17 00:00:00 2001 From: fred-venus Date: Tue, 16 Dec 2025 09:34:07 +0800 Subject: [PATCH 3/3] feat: update vip num and texxt --- .../abi/FlashLoanFacet.json | 0 .../abi/LeverageStrategiesManager.json | 0 .../{vip-575 => vip-576}/abi/SwapHelper.json | 0 .../{vip-575 => vip-576}/bscmainnet.ts | 4 +- vips/vip-575/bscmainnet.ts | 55 ------------------ vips/vip-576/bscmainnet.ts | 58 +++++++++++++++++++ 6 files changed, 60 insertions(+), 57 deletions(-) rename simulations/{vip-575 => vip-576}/abi/FlashLoanFacet.json (100%) rename simulations/{vip-575 => vip-576}/abi/LeverageStrategiesManager.json (100%) rename simulations/{vip-575 => vip-576}/abi/SwapHelper.json (100%) rename simulations/{vip-575 => vip-576}/bscmainnet.ts (95%) delete mode 100644 vips/vip-575/bscmainnet.ts create mode 100644 vips/vip-576/bscmainnet.ts diff --git a/simulations/vip-575/abi/FlashLoanFacet.json b/simulations/vip-576/abi/FlashLoanFacet.json similarity index 100% rename from simulations/vip-575/abi/FlashLoanFacet.json rename to simulations/vip-576/abi/FlashLoanFacet.json diff --git a/simulations/vip-575/abi/LeverageStrategiesManager.json b/simulations/vip-576/abi/LeverageStrategiesManager.json similarity index 100% rename from simulations/vip-575/abi/LeverageStrategiesManager.json rename to simulations/vip-576/abi/LeverageStrategiesManager.json diff --git a/simulations/vip-575/abi/SwapHelper.json b/simulations/vip-576/abi/SwapHelper.json similarity index 100% rename from simulations/vip-575/abi/SwapHelper.json rename to simulations/vip-576/abi/SwapHelper.json diff --git a/simulations/vip-575/bscmainnet.ts b/simulations/vip-576/bscmainnet.ts similarity index 95% rename from simulations/vip-575/bscmainnet.ts rename to simulations/vip-576/bscmainnet.ts index 5ef311fee..5f34ad220 100644 --- a/simulations/vip-575/bscmainnet.ts +++ b/simulations/vip-576/bscmainnet.ts @@ -5,7 +5,7 @@ import { NETWORK_ADDRESSES } from "src/networkAddresses"; import { expectEvents } from "src/utils"; import { forking, testVip } from "src/vip-framework"; -import { LEVERAGE_STRATEGIES_MANAGER, SWAP_HELPER, UNITROLLER, vip575 } from "../../vips/vip-575/bscmainnet"; +import vip576, { LEVERAGE_STRATEGIES_MANAGER, SWAP_HELPER, UNITROLLER } from "../../vips/vip-576/bscmainnet"; import COMPTROLLER_ABI from "./abi/FlashLoanFacet.json"; import LEVERAGE_STRATEGIES_MANAGER_ABI from "./abi/LeverageStrategiesManager.json"; import SWAP_HELPER_ABI from "./abi/SwapHelper.json"; @@ -54,7 +54,7 @@ forking(71263393, async () => { }); }); - testVip("VIP-575", await vip575(), { + testVip("VIP-576", await vip576(), { callbackAfterExecution: async txResponse => { await expectEvents(txResponse, [COMPTROLLER_ABI], ["IsAccountFlashLoanWhitelisted"], [1]); }, diff --git a/vips/vip-575/bscmainnet.ts b/vips/vip-575/bscmainnet.ts deleted file mode 100644 index 32a11ff22..000000000 --- a/vips/vip-575/bscmainnet.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { ProposalType } from "src/types"; -import { makeProposal } from "src/utils"; - -export const UNITROLLER = "0xfD36E2c2a6789Db23113685031d7F16329158384"; -export const LEVERAGE_STRATEGIES_MANAGER = "0x03F079E809185a669Ca188676D0ADb09cbAd6dC1"; -export const SWAP_HELPER = "0xD79be25aEe798Aa34A9Ba1230003d7499be29A24"; - -export const vip575 = () => { - const meta = { - version: "v2", - title: "VIP-575 [BNB Chain] Whitelist LeverageStrategiesManager for flash loans", - description: `#### Summary - -This VIP whitelists the LeverageStrategiesManager contract for flash loans on BNB Chain mainnet and accepts ownership of SwapHelper and LeverageStrategiesManager contracts. - -#### Description - -This VIP will: -- Accept ownership of [SwapHelper](https://bscscan.com/address/0xD79be25aEe798Aa34A9Ba1230003d7499be29A24) contract -- Accept ownership of [LeverageStrategiesManager](https://bscscan.com/address/0x03F079E809185a669Ca188676D0ADb09cbAd6dC1) contract -- Whitelist the [LeverageStrategiesManager](https://bscscan.com/address/0x03F079E809185a669Ca188676D0ADb09cbAd6dC1) contract to enable flash loan functionality for leverage strategies - -#### Deployed contracts - -- [LeverageStrategiesManager](https://bscscan.com/address/0x03F079E809185a669Ca188676D0ADb09cbAd6dC1) -- [SwapHelper](https://bscscan.com/address/0xD79be25aEe798Aa34A9Ba1230003d7499be29A24)`, - forDescription: "Execute", - againstDescription: "Do not execute", - abstainDescription: "Abstain", - }; - - return makeProposal( - [ - { - target: SWAP_HELPER, - signature: "acceptOwnership()", - params: [], - }, - { - target: LEVERAGE_STRATEGIES_MANAGER, - signature: "acceptOwnership()", - params: [], - }, - { - target: UNITROLLER, - signature: "setWhiteListFlashLoanAccount(address,bool)", - params: [LEVERAGE_STRATEGIES_MANAGER, true], - }, - ], - meta, - ProposalType.REGULAR, - ); -}; - -export default vip575; diff --git a/vips/vip-576/bscmainnet.ts b/vips/vip-576/bscmainnet.ts new file mode 100644 index 000000000..52bf4d9f2 --- /dev/null +++ b/vips/vip-576/bscmainnet.ts @@ -0,0 +1,58 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +export const UNITROLLER = "0xfD36E2c2a6789Db23113685031d7F16329158384"; +export const LEVERAGE_STRATEGIES_MANAGER = "0x03F079E809185a669Ca188676D0ADb09cbAd6dC1"; +export const SWAP_HELPER = "0xD79be25aEe798Aa34A9Ba1230003d7499be29A24"; + +export const vip576 = () => { + const meta = { + version: "v2", + title: "VIP-576 [BNB Chain] Implementation of Leveraged Positions (Boost & Repay)", + description: `This proposal is informed by the discussion in the Venus community forum [**Leveraged positions (Boost & Repay)**](https://community.venus.io/t/leveraged-positions-boost-repay/5593?utm_source=chatgpt.com), which outlines the implementation of the Leveraged Positions feature — encompassing “Boost” and “Repay with collateral” — in the Core Pool on BNB Chain. The community post describes the current inefficiencies of manual looping for leveraged strategies and proposes a single-transaction solution that automates leveraging and deleveraging with built-in safety checks, powered by flash loans under the hood. + +If approved, the Venus Protocol will execute the implementation of the Leveraged Positions feature as described in the community post, enabling users to create and manage recursive leveraged positions (Boost and Repay) via a seamless interface, enhancing user experience, capital efficiency, and protocol revenue potential. + +**Action :** + +- **Implement the Leveraged Positions feature in the Venus Core Pool on BNB Chain**: + - Enable **Boost** functionality to allow users to open leveraged positions via a single atomic transaction by automating the borrow → swap → supply loop using flash loans. + - Enable **Repay with collateral** functionality to allow users to repay, partially or fully, their debt using supplied collateral in one transaction, without requiring users to hold the borrowed asset externally. + - Develop and deploy the necessary user interface components that display: + - Maximum boostable amount + - Resulting leverage + - Updated health factor before confirmation + + as described in the community post. + + - Integrate underlying DEX aggregator support to facilitate efficient swaps required for Boost and Repay operations as described. + - Include risk warning and user acceptance toggle to ensure users are aware of increased risks associated with leveraged positions prior to execution.`, + forDescription: "Execute", + againstDescription: "Do not execute", + abstainDescription: "Abstain", + }; + + return makeProposal( + [ + { + target: SWAP_HELPER, + signature: "acceptOwnership()", + params: [], + }, + { + target: LEVERAGE_STRATEGIES_MANAGER, + signature: "acceptOwnership()", + params: [], + }, + { + target: UNITROLLER, + signature: "setWhiteListFlashLoanAccount(address,bool)", + params: [LEVERAGE_STRATEGIES_MANAGER, true], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip576;