Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mainnet deployment v1 #12

Merged
merged 6 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions script/RumpelGuardConfig.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity =0.8.24;

import {RumpelGuard} from "../src/RumpelGuard.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";

struct ProtocolConfig {
address target;
bytes4[] allowedSelectors;
}

struct TokenConfig {
address token;
bool allowTransfer;
bool allowApprove;
}

library RumpelGuardConfig {
// Protocols
address public constant MAINNET_MORPHO_BUNDLER = 0x4095F064B8d3c3548A3bebfd0Bbfd04750E30077;
address public constant MAINNET_ZIRCUIT_RESTAKING_POOL = 0xF047ab4c75cebf0eB9ed34Ae2c186f3611aEAfa6;
address public constant MAINNET_SYMBIOTIC_WSTETH_COLLATERAL = 0xC329400492c6ff2438472D4651Ad17389fCb843a;
address public constant MAINNET_SYMBIOTIC_SUSDE_COLLATERAL = 0x19d0D8e6294B7a04a2733FE433444704B791939A;
address public constant MAINNET_KARAK_VAULT_SUPERVISOR = 0x54e44DbB92dBA848ACe27F44c0CB4268981eF1CC;
address public constant MAINNET_ETHENA_LP_STAKING = 0x8707f238936c12c309bfc2B9959C35828AcFc512;

// Tokens
address public constant MAINNET_RSUSDE = 0x82f5104b23FF2FA54C2345F821dAc9369e9E0B26;
address public constant MAINNET_AGETH = 0xe1B4d34E8754600962Cd944B535180Bd758E6c2e;
address public constant MAINNET_SUSDE = 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497;
address public constant MAINNET_USDE = 0x4c9EDD5852cd905f086C759E8383e09bff1E68B3;
address public constant MAINNET_WSTETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0;
address public constant MAINNET_KUSDE = 0xBE3cA34D0E877A1Fc889BD5231D65477779AFf4e;
address public constant MAINNET_KWEETH = 0x2DABcea55a12d73191AeCe59F508b191Fb68AdaC;
address public constant MAINNET_WEETH = 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee;
address public constant MAINNET_MSTETH = 0x49446A0874197839D15395B908328a74ccc96Bc0;

function setupProtocols(RumpelGuard rumpelGuard) internal {
ProtocolConfig[] memory protocols = getProtocolConfigs();
for (uint256 i = 0; i < protocols.length; i++) {
ProtocolConfig memory config = protocols[i];
for (uint256 j = 0; j < config.allowedSelectors.length; j++) {
rumpelGuard.setCallAllowed(config.target, config.allowedSelectors[j], RumpelGuard.AllowListState.ON);
}
}
}

function setupTokens(RumpelGuard rumpelGuard) internal {
TokenConfig[] memory tokens = getTokenConfigs();
for (uint256 i = 0; i < tokens.length; i++) {
TokenConfig memory config = tokens[i];
if (config.allowTransfer) {
rumpelGuard.setCallAllowed(config.token, ERC20.transfer.selector, RumpelGuard.AllowListState.ON);
}
if (config.allowApprove) {
rumpelGuard.setCallAllowed(config.token, ERC20.approve.selector, RumpelGuard.AllowListState.ON);
}
}
}

function getProtocolConfigs() internal pure returns (ProtocolConfig[] memory) {
ProtocolConfig[] memory configs = new ProtocolConfig[](9);

// Morpho Bundler (supply, withdraw, borrow, repay)
configs[0] = ProtocolConfig({target: MAINNET_MORPHO_BUNDLER, allowedSelectors: new bytes4[](1)});
configs[0].allowedSelectors[0] = IMorphoBundler.multicall.selector;

// Zircuit Restaking Pool
configs[1] = ProtocolConfig({target: MAINNET_ZIRCUIT_RESTAKING_POOL, allowedSelectors: new bytes4[](2)});
configs[1].allowedSelectors[0] = IZircuitRestakingPool.depositFor.selector;
configs[1].allowedSelectors[1] = IZircuitRestakingPool.withdraw.selector;

// Symbiotic WstETH Collateral
configs[2] = ProtocolConfig({target: MAINNET_SYMBIOTIC_WSTETH_COLLATERAL, allowedSelectors: new bytes4[](2)});
configs[2].allowedSelectors[0] = ISymbioticWstETHCollateral.deposit.selector;
configs[2].allowedSelectors[1] = ISymbioticWstETHCollateral.withdraw.selector;

// Symbiotic SUSDe Collateral
configs[3] = ProtocolConfig({target: MAINNET_SYMBIOTIC_SUSDE_COLLATERAL, allowedSelectors: new bytes4[](2)});
configs[3].allowedSelectors[0] = ISymbioticWstETHCollateral.deposit.selector;
configs[3].allowedSelectors[1] = ISymbioticWstETHCollateral.withdraw.selector;

// Karak Vault Supervisor
configs[4] = ProtocolConfig({target: MAINNET_KARAK_VAULT_SUPERVISOR, allowedSelectors: new bytes4[](3)});
configs[4].allowedSelectors[0] = IKarakVaultSupervisor.deposit.selector;
configs[4].allowedSelectors[1] = IKarakVaultSupervisor.gimmieShares.selector;
configs[4].allowedSelectors[2] = IKarakVaultSupervisor.returnShares.selector;

// Mellow Ethena LRT Vault sUSDe
configs[5] = ProtocolConfig({target: MAINNET_RSUSDE, allowedSelectors: new bytes4[](2)});
configs[5].allowedSelectors[0] = IMellow.deposit.selector;
configs[5].allowedSelectors[1] = IMellow.registerWithdrawal.selector;

// KELP Airdrop Gain Vault
configs[6] = ProtocolConfig({target: MAINNET_AGETH, allowedSelectors: new bytes4[](4)});
configs[6].allowedSelectors[0] = IERC4626.deposit.selector;
configs[6].allowedSelectors[1] = IERC4626.mint.selector;
configs[6].allowedSelectors[2] = IERC4626.withdraw.selector;
configs[6].allowedSelectors[3] = IERC4626.redeem.selector;

// Ethena USDe staking
configs[7] = ProtocolConfig({target: MAINNET_SUSDE, allowedSelectors: new bytes4[](7)});
configs[7].allowedSelectors[0] = ISUSDE.unstake.selector;
configs[7].allowedSelectors[1] = ISUSDE.cooldownAssets.selector;
configs[7].allowedSelectors[2] = ISUSDE.cooldownShares.selector;
configs[7].allowedSelectors[3] = IERC4626.deposit.selector;
configs[7].allowedSelectors[4] = IERC4626.mint.selector;
configs[7].allowedSelectors[5] = IERC4626.withdraw.selector;
configs[7].allowedSelectors[6] = IERC4626.redeem.selector;

// Ethena USDe locking
configs[8] = ProtocolConfig({target: MAINNET_ETHENA_LP_STAKING, allowedSelectors: new bytes4[](2)});
configs[8].allowedSelectors[0] = IEthenaLpStaking.stake.selector;
configs[8].allowedSelectors[1] = IEthenaLpStaking.unstake.selector;

return configs;
}

function getTokenConfigs() internal pure returns (TokenConfig[] memory) {
TokenConfig[] memory configs = new TokenConfig[](11);

configs[0] = TokenConfig({token: MAINNET_SUSDE, allowTransfer: true, allowApprove: true});
configs[1] = TokenConfig({token: MAINNET_USDE, allowTransfer: true, allowApprove: true});
configs[2] = TokenConfig({token: MAINNET_WSTETH, allowTransfer: true, allowApprove: true});
configs[3] = TokenConfig({token: MAINNET_KUSDE, allowTransfer: true, allowApprove: true});
configs[4] = TokenConfig({token: MAINNET_KWEETH, allowTransfer: true, allowApprove: true});
configs[5] = TokenConfig({token: MAINNET_WEETH, allowTransfer: true, allowApprove: true});
configs[6] = TokenConfig({token: MAINNET_MSTETH, allowTransfer: true, allowApprove: true});
configs[7] = TokenConfig({token: MAINNET_RSUSDE, allowTransfer: true, allowApprove: false});
configs[8] = TokenConfig({token: MAINNET_AGETH, allowTransfer: true, allowApprove: false});
configs[9] = TokenConfig({token: MAINNET_SYMBIOTIC_WSTETH_COLLATERAL, allowTransfer: true, allowApprove: false});
configs[10] = TokenConfig({token: MAINNET_SYMBIOTIC_SUSDE_COLLATERAL, allowTransfer: true, allowApprove: false});

return configs;
}
}

interface IMorphoBundler {
function multicall(bytes[] memory data) external;
}

interface IZircuitRestakingPool {
function depositFor(address _token, address _for, uint256 _amount) external;
function withdraw(address _token, uint256 _amount) external;
}

interface ISymbioticWstETHCollateral {
function deposit(address recipient, uint256 amount) external returns (uint256);
function withdraw(address recipient, uint256 amount) external;
}

interface IERC4626 {
function deposit(uint256 assets, address receiver) external returns (uint256);
function mint(uint256 shares, address receiver) external returns (uint256);
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256);
function redeem(uint256 shares, address receiver, address owner) external returns (uint256);
}

interface ISUSDE {
function unstake(address receiver) external;
function cooldownAssets(uint256 assets) external returns (uint256 shares);
function cooldownShares(uint256 shares) external returns (uint256 assets);
}

interface IEthenaLpStaking {
function stake(address token, uint104 amount) external;
function unstake(address token, uint104 amount) external;
}

interface IKarakVaultSupervisor {
function deposit(address vault, uint256 amount, uint256 minSharesOut) external;
function gimmieShares(address vault, uint256 shares) external;
function returnShares(address vault, uint256 shares) external;
}

interface IMellow {
function deposit(address to, uint256[] memory amounts, uint256 minLpAmount, uint256 deadline)
external
returns (uint256[] memory actualAmounts, uint256 lpAmount);
function registerWithdrawal(
address to,
uint256 lpAmount,
uint256[] memory minAmounts,
uint256 deadline,
uint256 requestDeadline,
bool closePrevious
) external;
}
33 changes: 24 additions & 9 deletions script/RumpelWalletFactory.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,26 @@ import {RumpelGuard} from "../src/RumpelGuard.sol";
import {CompatibilityFallbackHandler, ValidationBeacon} from "../src/external/CompatibilityFallbackHandler.sol";
import {ISafeProxyFactory} from "../src/interfaces/external/ISafeProxyFactory.sol";
import {ISafe} from "../src/interfaces/external/ISafe.sol";
import {RumpelGuardConfig} from "./RumpelGuardConfig.sol";

contract RumpelWalletFactoryScripts is Script {
address public MAINNET_ADMIN = 0x9D89745fD63Af482ce93a9AdB8B0BbDbb98D3e06;
address public MAINNET_RUMPEL_VAULT = 0x1EeEBa76f211C4Dce994b9c5A74BDF25DB649Fa1;
address public MAINNET_SAFE_SINGLETON = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552;
ISafeProxyFactory public MAINNET_SAFE_PROXY_FACTORY = ISafeProxyFactory(0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2);

address public MAINNET_SIGN_MESSAGE_LIB = 0xA65387F16B013cf2Af4605Ad8aA5ec25a2cbA3a2;
// TODO
address public MAINNET_RUMPEL_VAULT = 0x1EeEBa76f211C4Dce994b9c5A74BDF25DB649Fa1; // TODO: update with new address after vault deployment
// TODO

address public MAINNET_SAFE_SINGLETON = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552; // 1.3.0
address public MAINNET_SIGN_MESSAGE_LIB = 0xA65387F16B013cf2Af4605Ad8aA5ec25a2cbA3a2; // 1.3.0
address public MAINNET_SAFE_PROXY_FACTORY = 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2; // 1.3.0

function setUp() public {}

function run() public {
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");

vm.startBroadcast(deployerPrivateKey);
run(msg.sender);
run(MAINNET_ADMIN);
vm.stopBroadcast();
}

Expand All @@ -37,13 +41,13 @@ contract RumpelWalletFactoryScripts is Script {

ValidationBeacon validationBeacon = new ValidationBeacon();
CompatibilityFallbackHandler compatibilityFallbackHandler =
new CompatibilityFallbackHandler(msg.sender, validationBeacon);
new CompatibilityFallbackHandler(admin, validationBeacon);

// Script that will be delegatecalled to enable modules
InitializationScript initializationScript = new InitializationScript();

RumpelWalletFactory rumpelWalletFactory = new RumpelWalletFactory(
MAINNET_SAFE_PROXY_FACTORY,
ISafeProxyFactory(MAINNET_SAFE_PROXY_FACTORY),
address(compatibilityFallbackHandler),
MAINNET_SAFE_SINGLETON,
address(rumpelModule),
Expand All @@ -55,14 +59,16 @@ contract RumpelWalletFactoryScripts is Script {
rumpelModule.addBlockedModuleCall(address(0), ISafe.enableModule.selector);
// Prevent us from disabling the module.
rumpelModule.addBlockedModuleCall(address(0), ISafe.disableModule.selector);
// Prevent us from setting the guard.
rumpelModule.addBlockedModuleCall(address(0), ISafe.setGuard.selector);

// Allow Safes to delegate pToken claiming
rumpelGuard.setCallAllowed(
MAINNET_RUMPEL_VAULT, PointTokenVault.trustClaimer.selector, RumpelGuard.AllowListState.ON
);

// Populate initial allowlist
RumpelGuardConfig.setupProtocols(rumpelGuard);
RumpelGuardConfig.setupTokens(rumpelGuard);

rumpelGuard.transferOwnership(admin);
rumpelModule.transferOwnership(admin);
rumpelWalletFactory.transferOwnership(admin);
Expand Down Expand Up @@ -94,4 +100,13 @@ contract RumpelWalletFactoryScripts is Script {
addModuleCallBlocked(rumpelModule, target, functionSelector);
setCallAllowed(rumpelGuard, target, functionSelector, RumpelGuard.AllowListState.PERMANENTLY_ON);
}

function addBlockedModuleCall(RumpelModule rumpelModule, address target, bytes4 functionSelector) public {
rumpelModule.addBlockedModuleCall(target, functionSelector);
}

// TODO: don't forget to make this call in the future
function addSetGuardBlocked(RumpelModule rumpelModule) public {
rumpelModule.addBlockedModuleCall(address(0), ISafe.setGuard.selector);
}
}