Skip to main content

Multi-User Staking with Additional Yield via Custom DeFi Strategy

Product value proposition​

An end-user staking product with a higher risk/yield profile achieved by depositing stETH minted from the stVault into a custom DeFi strategy, with a user-friendly interface that can be embedded into your own or a partner’s distribution channel.

Product characteristics​

ParameterValue
Number of stakersMultiple
stETH minting capabilityYes, to deposit into a custom DeFi strategy and generate additional DeFi yield

Building blocks​

Building blockSolutionImplementation
BasisstVaultOut-of-the-box
Pooling WrapperDeFi WrapperOut-of-the-box
Connector to DeFi StrategyCustom connectorCustom
User InterfaceDeFi Wrapper Embeddable Widget / CustomOut-of-the-box / Custom

What is DeFi Wrapper?​

The DeFi Wrapper is a no-/low-code toolkit that lets builders, Node Operators, and platforms launch customized user-facing staking products powered by stVaults β€” with optional automated APR-boosting strategies such as leverage loops or any custom stETH-based yield module.

Architecture​

Multi-User Staking with Additional Yield via Custom DeFi Strategy

Steps​

➑️ URLs and Smart Contract addresses are listed on Environments

This guide walks through how to build and deploy a pooled staking product with a custom yield strategy using the DeFi Wrapper toolkit.

The DeFi Wrapper architecture is designed to support any custom strategy as long as it implements the required interfaces.

There are two paths to getting a pool with a custom strategy:

  1. Deploy from scratch - Already have a custom strategy and ready to launch a pool

  2. Upgrade existing pool - Create a pool and add a custom strategy later

Both paths share the same smart-contract development steps (implementing IStrategy and IStrategyFactory).

Smart contract development​

  1. Implement the IStrategy interface

  2. Implement the IStrategyFactory interface. The _deployBytes parameter can be used to pass additional strategy-specific configuration during deployment. If your strategy doesn't need extra config, it can be ignored.

  3. Deploy the strategy factory

note

Note the deployed strategy factory address β€” you will need it in Path A.

warning

Make sure to deploy the strategy factory on the same network where you will create the pool (Hoodi testnet for testing, Ethereum mainnet for production).


Path A: Deploy a new pool with custom strategy​

Use this path when launching a new product from scratch.

Create the pool via CLI​

Use the create-pool-custom command to deploy the pool with your strategy:

yarn start defi-wrapper contracts factory w create-pool-custom <DEFI_WRAPPER_FACTORY> \
--nodeOperator <NODE_OPERATOR_ADDRESS> \
--nodeOperatorManager <NODE_OPERATOR_MANAGER_ADDRESS> \
--nodeOperatorFeeRateBP 10 \
--confirmExpiry 86400 \
--minDelaySeconds 3600 \
--minWithdrawalDelayTime 3600 \
--name "Strategy Pool" \
--symbol STV \
--proposer <PROPOSER_ADDRESS> \
--executor <EXECUTOR_ADDRESS> \
--emergencyCommittee <EMERGENCY_COMMITTEE_ADDRESS> \
--reserveRatioGapBP 250 \
--mintingEnabled true \
--allowList true \
--allowListManager 0x0000000000000000000000000000000000000000 \
--strategyFactory <MY_STRATEGY_FACTORY_ADDRESS> \
--strategyFactoryDeployBytes <strategyFactoryDeployBytes>

Run yarn start defi-wrapper contracts factory write create-pool-custom -h for the full description of all available parameters.

warning

On a strategy pool --allowListManager has to be the zero address. The CLI rejects any other value while --strategyFactory is set, since that role decides which strategies may deposit into the pool.

info

The deployer must have at least 1 ETH available. This is the CONNECT_DEPOSIT required to be locked on the stVault upon connection to Lido VaultHub.

Parameter reference
ParameterDescription
<DEFI_WRAPPER_FACTORY>DeFi Wrapper Factory contract address (see Environments)
--nodeOperatorAddress of the Node Operator managing validators
--nodeOperatorManagerAddress authorized to manage Node Operator settings
--nodeOperatorFeeRateBPNode Operator fee in basis points (10 = 0.1%)
--confirmExpiryConfirmation timeout in seconds
--minDelaySecondsTimeLock minimum delay before execution
--minWithdrawalDelayTimeMinimum delay before withdrawals can be finalized
--nameERC-20 pool share token name; the CLI enforces 3–14 characters
--symbolERC-20 pool share token symbol; the CLI enforces 3–8 characters
--proposerAddress authorized to propose TimeLock operations
--executorAddress authorized to execute TimeLock operations
--emergencyCommitteeAddress that can pause pool operations
--reserveRatioGapBPReserve ratio gap in basis points (recommended min: 250)
--mintingEnabledEnable stETH minting (true / false)
--allowListEnable deposit allowlist (true / false)
--allowListManagerAddress managing the allowlist. Must be the zero address on a strategy pool.
--strategyFactoryYour deployed strategy factory address
--strategyFactoryDeployBytesOptional hex-encoded bytes passed to your factory's deploy()
warning

The minimum recommended value for reserveRatioGapBP is 250 (2.5%). It is expected to be sufficient to absorb enough of the stVault's performance volatility to keep users' positions healthy in most cases.

After successful deployment, the CLI outputs the addresses and environment variables you need:

The first transaction prints the Dashboard, Pool Proxy, Withdrawal Queue Proxy and TimeLock; the second adds the Vault, Pool, Pool Type, Withdrawal Queue, Strategy Factory and Strategy, along with the UI environment variables (VITE_POOL_ADDRESS, VITE_POOL_TYPE).

The Distributor address is not printed. Read it later with yarn start dw uc wo r info <poolAddress>, which returns the whole set β€” see Per-setup addresses.

info

Keep the CLI output β€” you will need these addresses for the UI setup and ongoing operations.

Continue with Post-deployment steps.


Path B: Upgrade an existing pool to a strategy pool​

Use this path when you have a running StvStETHPool and want to add a strategy without redeploying the pool. All existing user balances and state are preserved through the proxy upgrade.

info

This upgrade path uses the OssifiableProxy pattern. The pool contract is a proxy whose implementation can be swapped by its admin (the TimelockController). Storage (user balances, roles, parameters) lives in the proxy and is preserved across implementation changes.

What changes during the upgrade​

AspectBefore (StvStETHPool)After (StvStrategyPool)
Pool typeSTV_STETH_POOL_TYPESTRATEGY_POOL_TYPE
AllowlistDisabledEnabled (only strategy can deposit)
StrategyNoneYour custom strategy contract
Direct user depositsAllowedBlocked (users go through strategy)
User STV balancesβœ… Preservedβœ… Preserved
Vault, Dashboard, WQβœ… Unchangedβœ… Unchanged

Deploy the new pool implementation and strategy​

You need two new contracts: a new pool implementation (with STRATEGY_POOL_TYPE and allowListEnabled = true) and the strategy itself.

Deploy new pool implementation​

Use the existing StvStETHPoolFactory to create a new implementation with the correct pool type:

cast send <STV_STETH_POOL_FACTORY> \
"deploy(address,bool,uint256,address,address,bytes32)(address)" \
<DASHBOARD> \
true \
<RESERVE_RATIO_GAP_BP> \
<WITHDRAWAL_QUEUE> \
<DISTRIBUTOR> \
<STRATEGY_POOL_TYPE> \
--rpc-url $RPC_URL \
--private-key $DEPLOYER_KEY

Parameters:

  • <STV_STETH_POOL_FACTORY> β€” the StvStETHPoolFactory address from the DeFi Wrapper Factory (Factory.STV_STETH_POOL_FACTORY())
  • <DASHBOARD> β€” your pool's existing Dashboard address
  • true β€” enables the allowlist (immutable in the new implementation)
  • <RESERVE_RATIO_GAP_BP> β€” the existing pool's value, readable with poolReserveRatioBP minus the stVault's ratio; 250 in the shipped configurations
  • <WITHDRAWAL_QUEUE> β€” your pool's existing WithdrawalQueue address
  • <DISTRIBUTOR> β€” your pool's existing Distributor address
  • <STRATEGY_POOL_TYPE> β€” the strategy pool type hash (Factory.STRATEGY_POOL_TYPE())

Note the deployed new pool implementation address.

Deploy strategy implementation​

Deploy the strategy implementation contract. For example:

forge create src/strategy/MyStrategy.sol:MyStrategy \
--rpc-url $RPC_URL \
--private-key $DEPLOYER_KEY \
--broadcast \
--constructor-args <CONSTRUCTOR_ARGS>

Note the deployed strategy implementation address.

Deploy strategy proxy​

The strategy must be deployed behind an OssifiableProxy. The proxy is created with three parameters:

  • implementation_ β€” the strategy implementation address from the previous step
  • admin_ β€” the pool's TimelockController address (proxy admin who can upgrade the implementation)
  • data_ β€” the ABI-encoded initialize calldata to be executed on the implementation during proxy creation

First, encode the initialize calldata:

INITIALIZE_CALLDATA=$(cast calldata "initialize(address,address)" <TIMELOCK> <EMERGENCY_COMMITTEE>)

Where:

  • <TIMELOCK> β€” the pool's TimelockController address (will receive DEFAULT_ADMIN_ROLE on the strategy)
  • <EMERGENCY_COMMITTEE> β€” address that receives SUPPLY_PAUSE_ROLE; pass the zero address to grant it to nobody

Then deploy the proxy:

forge create src/proxy/OssifiableProxy.sol:OssifiableProxy \
--rpc-url $RPC_URL \
--private-key $DEPLOYER_KEY \
--broadcast \
--constructor-args <STRATEGY_IMPL> <TIMELOCK> $INITIALIZE_CALLDATA

Note the deployed strategy proxy address β€” this is the address you will use in the TimelockController batch below.

warning

The proxy admin must be the pool's TimelockController address. The initialize call sets the Timelock as the strategy's DEFAULT_ADMIN_ROLE holder.

Execute the upgrade via TimelockController batch​

The upgrade must be executed as an atomic batch through the TimelockController to prevent an intermediate state where the allowlist is enabled but the strategy is not yet allowlisted.

The batch consists of operations, all targeting the pool proxy:

warning

The exact number and content of operations depends on the current pool configuration (e.g., whether minting is paused, which roles are assigned). The example below is illustrative and may differ in your case.

#OperationPurpose
1proxy__upgradeToAndCall(newImpl, "")Swap implementation to strategy pool type
2grantRole(ALLOW_LIST_MANAGER_ROLE, timelock)Temporarily grant allowlist management to Timelock
3addToAllowList(strategyProxy)Allow the strategy to deposit into the pool
4revokeRole(ALLOW_LIST_MANAGER_ROLE, factory)Remove the Factory's allowlist management. Not optional: the Factory has held this role since the pool was created, and the upgrade is what makes it usable
5revokeRole(ALLOW_LIST_MANAGER_ROLE, timelock)Remove Timelock's temporary allowlist management
6revokeRole(DEPOSITS_PAUSE_ROLE, nodeOperator)Adjust pause roles for the new setup
7revokeRole(MINTING_PAUSE_ROLE, nodeOperator)Adjust pause roles for the new setup
8grantRole(MINTING_RESUME_ROLE, timelock)Temporarily grant minting resume capability
9resumeMinting()Re-enable minting (needed if paused in the original pool)
10revokeRole(MINTING_RESUME_ROLE, timelock)Remove temporary minting resume capability
info

Steps 8–10 (resume minting) are only needed if minting was paused in the original pool. If minting was already active, these steps can be omitted from the batch.

info

Steps 6–7 (revoke pause roles from the Node Operator) adjust the emergency role setup to match the strategy pool configuration. Review the DeFi Wrapper roles and permissions to decide what role assignment is appropriate for your setup.

Step 1: Prepare calldata for each operation

Use cast (from Foundry) to encode each payload:

# 1. Upgrade pool implementation
PAYLOAD_1=$(cast calldata "proxy__upgradeToAndCall(address,bytes)" <NEW_POOL_IMPL> 0x)

# 2. Grant ALLOW_LIST_MANAGER_ROLE to timelock
ALLOW_LIST_MANAGER_ROLE=$(cast call <POOL> "ALLOW_LIST_MANAGER_ROLE()(bytes32)" --rpc-url $RPC_URL)
PAYLOAD_2=$(cast calldata "grantRole(bytes32,address)" $ALLOW_LIST_MANAGER_ROLE <TIMELOCK>)

# 3. Add strategy to allowlist
PAYLOAD_3=$(cast calldata "addToAllowList(address)" <STRATEGY_PROXY>)

# 4. Revoke ALLOW_LIST_MANAGER_ROLE from factory
PAYLOAD_4=$(cast calldata "revokeRole(bytes32,address)" $ALLOW_LIST_MANAGER_ROLE <FACTORY>)

# 5. Revoke ALLOW_LIST_MANAGER_ROLE from timelock
PAYLOAD_5=$(cast calldata "revokeRole(bytes32,address)" $ALLOW_LIST_MANAGER_ROLE <TIMELOCK>)

# 6. Revoke DEPOSITS_PAUSE_ROLE from node operator
DEPOSITS_PAUSE_ROLE=$(cast call <POOL> "DEPOSITS_PAUSE_ROLE()(bytes32)" --rpc-url $RPC_URL)
PAYLOAD_6=$(cast calldata "revokeRole(bytes32,address)" $DEPOSITS_PAUSE_ROLE <NODE_OPERATOR>)

# 7. Revoke MINTING_PAUSE_ROLE from node operator
MINTING_PAUSE_ROLE=$(cast call <POOL> "MINTING_PAUSE_ROLE()(bytes32)" --rpc-url $RPC_URL)
PAYLOAD_7=$(cast calldata "revokeRole(bytes32,address)" $MINTING_PAUSE_ROLE <NODE_OPERATOR>)

# 8. Grant MINTING_RESUME_ROLE to timelock
MINTING_RESUME_ROLE=$(cast call <POOL> "MINTING_RESUME_ROLE()(bytes32)" --rpc-url $RPC_URL)
PAYLOAD_8=$(cast calldata "grantRole(bytes32,address)" $MINTING_RESUME_ROLE <TIMELOCK>)

# 9. Resume minting
PAYLOAD_9=$(cast calldata "resumeMinting()")

# 10. Revoke MINTING_RESUME_ROLE from timelock
PAYLOAD_10=$(cast calldata "revokeRole(bytes32,address)" $MINTING_RESUME_ROLE <TIMELOCK>)
Step 2: Schedule the batch (Proposer)

Call TimelockController.scheduleBatch on the Timelock contract. This can be done via Etherscan or cast:

POOL=<POOL_ADDRESS>
PREDECESSOR=0x0000000000000000000000000000000000000000000000000000000000000000
SALT=0x0000000000000000000000000000000000000000000000000000000000000000
DELAY=<MIN_DELAY_SECONDS>

cast send <TIMELOCK> \
"scheduleBatch(address[],uint256[],bytes[],bytes32,bytes32,uint256)" \
"[$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL]" \
"[0,0,0,0,0,0,0,0,0,0]" \
"[$PAYLOAD_1,$PAYLOAD_2,$PAYLOAD_3,$PAYLOAD_4,$PAYLOAD_5,$PAYLOAD_6,$PAYLOAD_7,$PAYLOAD_8,$PAYLOAD_9,$PAYLOAD_10]" \
$PREDECESSOR \
$SALT \
$DELAY \
--rpc-url $RPC_URL \
--private-key $PROPOSER_KEY

Note the operation ID from the CallScheduled event in the transaction logs.

Step 3: Execute the batch (Executor)

After the timelock delay has passed, execute the batch:

cast send <TIMELOCK> \
"executeBatch(address[],uint256[],bytes[],bytes32,bytes32)" \
"[$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL,$POOL]" \
"[0,0,0,0,0,0,0,0,0,0]" \
"[$PAYLOAD_1,$PAYLOAD_2,$PAYLOAD_3,$PAYLOAD_4,$PAYLOAD_5,$PAYLOAD_6,$PAYLOAD_7,$PAYLOAD_8,$PAYLOAD_9,$PAYLOAD_10]" \
$PREDECESSOR \
$SALT \
--rpc-url $RPC_URL \
--private-key $EXECUTOR_KEY

You can verify the operation is ready before executing:

cast call <TIMELOCK> "isOperationReady(bytes32)(bool)" <OPERATION_ID> --rpc-url $RPC_URL

Verify the upgrade via CLI​

yarn start defi-wrapper use-cases wrapper-operations read info <POOL_ADDRESS>
yarn start vo r info -v <VAULT_ADDRESS>

What users experience after the upgrade​

  • Existing STV balances are fully preserved β€” users keep their tokens.
  • Direct deposits to the pool are no longer possible (blocked by allowlist). Users must go through the strategy.
  • Existing STV holders can move into the strategy, but not by approving it: the strategy has no function that pulls stv from a user's address. supply either takes ETH or mints against stv the user's forwarder already holds. To migrate, transfer the stv to that forwarder β€” its address is deterministic and readable with getStrategyCallForwarderAddress(user) β€” and then call supply with a non-zero wstETH amount.
  • Withdrawals of existing STV continue to work through the WithdrawalQueue as before.

Reference implementation​

The MellowStrategy (Lido EarnETH Strategy) and its MellowStrategyFactory serve as the reference implementation for custom strategies.

Study them to understand the complete pattern, including:

  • How StrategyCallForwarderRegistry manages per-user proxies
  • How FeaturePausable enables granular pause control
  • How to handle ERC-20 approvals and transfers through call forwarders
  • How to implement cancel/replace flows for pending exit requests
  • How the proxy upgrade preserves all user state

The upgrade integration test demonstrates the complete StvStETHPool β†’ strategy pool upgrade flow.

Create Web UI​

If your custom strategy has an interface and operations similar to Lido EarnETH, you can use the out-of-the-box DeFi Wrapper embeddable widget with minor modifications. Follow this guide to:

  • Clone the provided repository
  • Use addresses outputted by CLI to fill up .env
  • Adjust titles, logos, texts, and color scheme to your liking
  • Deploy the dApp

Adjust stETH minting parameters​

By default, a newly created stVault is connected to the Default tier with a Reserve Ratio of 50%. If the Node Operator has passed identification and been granted individual tiers, the stVault can be moved from the Default tier to one of the Node Operator’s tiers to access better stETH minting conditions.

For more information about how this process works for the Basic stVault, please follow Adjust stETH minting parameters.

For stVaults with DeFi Wrapper the process of changing tier is a bit different because the Vault Owner role is assigned to the Timelock contract. The Timelock contract itself implements a two-step process for performing an on-chain action. First, the holder of its proposer role creates a proposed on-chain action; second, after a time period, the holder of the executor role executes it.

Thus, changing tier for a pooled vault is a three-step process:

  1. Holder of the Timelock's proposer role calls TimelockController.schedule to propose the Dashboard.changeTier call
  2. After the timelock period, the holder of the Timelock's executor role calls TimelockController.execute for the scheduled proposal
  3. Within the OperatorGrid confirmation expiry (currently 24 hours), the Node Operator confirms from their side by calling OperatorGrid.changeTier(vault, tierId, requestedShareLimit) β€” the same tier and share limit, but through a different contract and with the stVault as an extra argument

Confirming tier change request requires applying fresh report to vault. Read more about applying reports

Parameters needed for this step:

  • VaultAddress: the address of the Vault contract.
  • TierID: the ID of the tier to which the stVault will be connected.
  • RequestedShareLimit: the requested absolute stETH minting limit for the stVault, expressed in shares. This value cannot exceed the tier's stETH limit.
  • TimelockAddress: the address of the TimelockController contract (deployed together with the pool).
  • OperatorGridAddress: the address of the OperatorGrid contract (available in the stVaults contract addresses list, see Environments).
How to determine available tier IDs for your Node Operator

To find out which tier IDs are available for your Node Operator, you can use:

CLI:

# Get group information for your Node Operator (shows all available tier IDs)
yarn start contracts operator-grid r group <nodeOperatorAddress>

# Get information about a specific tier
yarn start contracts operator-grid r tier <tierId>

Contract call (Etherscan):

  • Navigate to the OperatorGrid contract address
  • Go to Contract β†’ Read Contract
  • Call group(nodeOperatorAddress) to get the Group struct, which includes the tierIds array
  • Call tier(tierId) to get details about a specific tier

The group method returns a struct containing:

  • operator: Node operator address
  • shareLimit: Maximum liability shares across all group vaults
  • liabilityShares: Current liability shares in the group
  • tierIds: Array of tier IDs belonging to this Node Operator
Step 1: Schedule the tier change (Proposer)

CLI​

Use --wallet-connect option for all commands or provide private key to CLI .env

  1. Get address of your timelock contract:
    yarn start defi-wrapper use-cases timelock-governance common read get-timelock-address <poolAddress>
  2. Connect wallet that holds the proposer role to CLI
  3. Propose change tier
    yarn start defi-wrapper use-cases timelock-governance dashboard write propose-change-tier <timelockAddress> <dashboard> <tierId> <shareLimit>

Etherscan​

  1. Open Etherscan and navigate to the TimelockController contract β€” find its address on the Per-setup addresses page.
  2. Go to the Contract tab β†’ Write Contract.
  3. Click Connect to Web3 and connect the wallet that holds the proposer role.
  4. Find the schedule method in the list and fill out the fields:
    • target: the Dashboard contract address.
    • value: 0 (no ETH is sent with this call).
    • data: the ABI-encoded call to changeTier(uint256 tierId, uint256 requestedShareLimit). You can generate this using tools like ABI Encoder or cast from Foundry:
      cast calldata "changeTier(uint256,uint256)" <TierID> <RequestedShareLimit>
    • predecessor: 0x0000000000000000000000000000000000000000000000000000000000000000 (no predecessor required).
    • salt: 0x0000000000000000000000000000000000000000000000000000000000000000 (or any unique value if you need to differentiate identical operations).
    • delay: the delay in seconds (must be at least the minDelaySeconds configured during pool deployment).
  5. Click Write and sign the transaction in your wallet.
  6. Click View your transaction and wait for it to be executed.
  7. Note down the operation ID from the CallScheduled event in the transaction logs β€” you will need it to verify the operation status before execution.
Step 2: Execute the scheduled tier change (Executor)

CLI​

  1. Check the timelock delay period:

    # Get timelock address
    yarn start defi-wrapper use-cases timelock-governance common read get-timelock-address <poolAddress>

    # Then get the minimum delay (replace <timelockAddress> with the address from previous command)
    yarn start defi-wrapper use-cases timelock-governance common read get-min-delay <timelockAddress>
  2. Wait for the timelock delay period to pass. You can verify the operation is ready by calling

    yarn start defi-wrapper use-cases timelock-governance common read get-last-operations <timelockAddress>
  3. Connect wallet that holds the executor role to CLI

  4. Execute change tier

    yarn start defi-wrapper use-cases timelock-governance dashboard write execute-change-tier <timelockAddress> <dashboard> <tierId> <shareLimit>

Etherscan​

  1. Check the timelock delay period:

    • Open Etherscan and navigate to the TimelockController contract β€” find its address on the Per-setup addresses page.
    • Go to the Contract tab β†’ Read Contract.
    • Find the getMinDelay method and click Query to see the minimum delay in seconds.
  2. Wait for the timelock delay period to pass. You can verify the operation is ready by calling isOperationReady(operationId) on the TimelockController contract (in Read Contract tab).

  3. Execute change tier, connect the wallet:

    • Open Etherscan and navigate to the TimelockController contract β€” find its address on the Per-setup addresses page.
    • Go to the Contract tab β†’ Write Contract.
    • Click Connect to Web3 and connect the wallet that holds the executor role.
  4. Find the execute method in the list and fill out the fields with the same values used in the schedule call:

    • target: the Dashboard contract address.
    • value: 0.
    • payload: the same ABI-encoded call data used in step 1.
    • predecessor: 0x0000000000000000000000000000000000000000000000000000000000000000.
    • salt: the same salt value used in step 1.
  5. Click Write and sign the transaction in your wallet.

  6. Click View your transaction and wait for it to be executed.

Step 3: Confirm the tier change (Node Operator)

Within the OperatorGrid confirmation expiry (currently 24 hours) after step 2, the Node Operator must confirm the tier change:

stVaults UI​

  1. Go to https://stvaults.lido.fi/vaults/[vaultAddress]/settings/tier
  2. Connect wallet that has Node operator address
  3. Follow UI to confirm tier change

CLI​

  1. Connect wallet that has Node operator address to CLI
  2. yarn start vo w change-tier-by-no -v <vaultAddress> -r <requestedShareLimit> <tierId>

Etherscan​

  1. Open Etherscan and navigate to the OperatorGrid contract by its address (available in the stVaults contract addresses list, see Environments).
  2. Since this contract is a proxy, complete the verification steps once (if not done before):
    • Go to Contract β†’ Code.
    • Click More options.
    • Select Is this a proxy?.
    • Click Verify in the dialog.
    • Return to the contract details page.
  3. Open the Contract tab β†’ Write as Proxy.
  4. Click Connect to Web3 and connect the wallet registered as the Node Operator.
  5. Find the changeTier method in the list and fill out the fields with the same values used in steps 1 and 2:
    • vault: the Vault contract address.
    • tierId: the tier ID.
    • requestedShareLimit: the requested share limit.
  6. Click Write and sign the transaction in your wallet.
  7. Click View your transaction and wait for it to be executed.