Skip to content

Commit 92c6f65

Browse files
committed
feat: enhance documentation for Liquid Restaking Tokens (LRT)
- Update metadata and introduction for LRT developers - Improve comparison table between LRT and LST - Add detailed explanation of building LRT on Tangle Network - Clarify core concepts of liquid restaking and delegation vaults
1 parent a4daeee commit 92c6f65

File tree

5 files changed

+372
-5
lines changed

5 files changed

+372
-5
lines changed

pages/restake/lrt-concepts.mdx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
# Liquid Restaking on Tangle Network
3+
4+
## Introduction
5+
6+
Liquid restaking allows users to participate in staking while still maintaining liquidity of their staked assets.
7+
This mechanism is implemented via delegation vaults, enabling participants to stake their tokens in a vault, earn rewards, and retain the ability to unbond or transfer staked assets without waiting for the traditional staking lock-up periods.
8+
9+
## Core Concepts
10+
11+
### Delegation Vaults
12+
13+
Delegation vaults are the backbone of liquid restaking on Tangle Network. These vaults:
14+
15+
- Allow users to deposit tokens which are then delegated to Tangle operators running blueprint services
16+
- Issue shares (liquid tokens) representing the user's deposited assets
17+
- Handle the complexities of managing deposits, unstaking, and withdrawals
18+
- Rewards distribution and claiming.
19+
20+
### Liquid Tokens
21+
22+
When users deposit assets into a liquid restaking vault, they receive shares in return. These shares:
23+
24+
- Represent ownership of the underlying staked assets
25+
- Can be transferred or traded while the underlying assets remain staked
26+
- Serve as a claim ticket for both the original deposit and earned rewards
27+
- Do not automatically increase in value like traditional LSTs but instead provide access to claim rewards
28+
29+
### Multi-step Withdrawal Process
30+
31+
The withdrawal process in liquid restaking involves multiple steps:
32+
33+
1. **Schedule Unstake**: User initiates the unstaking process from the operator
34+
2. **Execute Unstake**: The unstaking request is processed after the unbonding period
35+
3. **Schedule Withdrawal**: User requests to withdraw their assets from the vault
36+
4. **Execute Withdrawal**: The final withdrawal is processed, returning assets to the user
37+
38+
This process ensures orderly exits while maintaining the security of the network.
39+
40+
### Rewards Distribution
41+
42+
Liquid restaking vaults use an accumulator-based system for tracking and distributing rewards:
43+
44+
- Each reward token has a global accumulator tracking rewards-per-share over time
45+
- User positions are tracked by snapshots recording their share balance and last claim point
46+
- Rewards are calculated based on the difference between current and last-seen accumulator values
47+
- This system ensures fair distribution regardless of when users entered the pool or how many shares they hold
48+
49+
### Operator Delegation
50+
51+
Vaults will automatically delegate deposited assets to selected Tangle operators who:
52+
53+
- Run blueprint services on the network
54+
- Generate rewards through their participation

pages/restake/lrt-vs-lst.mdx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## Liquid Restaking Tokens (LRT) vs Liquid Staking Tokens (LST)
2+
3+
| Feature | LRT (Tangle Network) | LST (Traditional) |
4+
|-----------------------|-----------------------------------------------|--------------------------------------|
5+
| Primary Function | Enables restaking across multiple Blueprints | Provides liquidity for staked assets|
6+
| Risk Profile | Shared security across services | Single network exposure |
7+
| Reward Sources | Multiple Services rewards + staking yields | Base chain staking rewards |
8+
| Use Cases | Cross-service validation, Blueprint creation | Trading, lending, DeFi integrations |
9+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"intro": "Introduction",
3+
"lrt-vault": "Creating a LRT on Tangle"
4+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Building LRT on Tangle Network
2+
3+
Tangle Multi-Asset Delegations (MADs) pallet precompile provides information about the current state of the Tangle network restaking functionality.
4+
A precompiled contract is native Substrate code that has an Ethereum-style address and can be called using the Ethereum API, like any other smart contract.
5+
The precompiles allow you to call the Substrate runtime directly which is not normally accessible from the Ethereum side of Tangle.
6+
7+
### How to use the precompile
8+
9+
We have a detailed page about the [Multi-Asset Delegation Precompile](../../developers/precompiles/features/multi-asset-delegation.mdx).
10+
11+
In the next page, we will have a tutorial about how to use this precompile to build a LRT on Tangle.
12+
Lines changed: 293 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,295 @@
1-
# LRT Developers
1+
# Creating a LRT Vault on Tangle
22

3-
The LRT Developers section provides insights into the tools and resources available for developers working with the Tangle Network. This includes the Gadget SDK and other tools that enable the creation and deployment of Blueprints for Actively Validated Services (AVS).
3+
## Overview
44

5-
## Key Resources
6-
- **Gadget SDK**: A powerful tool for building Blueprints.
7-
- **Documentation**: Comprehensive guides and tutorials for developers.
5+
This tutorial walks through creating a Liquid Restaking Token (LRT) Vault on Tangle Network using the reference implementation from the [tangle-lrt](https://github.com/tangle-network/lrt) repository. LRT vaults allow users to receive liquid tokens representing their staked assets while participating in Tangle's restaking mechanism.
6+
7+
## Prerequisites
8+
9+
- Basic knowledge of Solidity and EVM development
10+
- [Foundry](https://book.getfoundry.sh/) installed for smart contract development
11+
- MetaMask wallet connected to Tangle Network
12+
- Some test tokens for deployment (on testnet)
13+
14+
Install Foundry:
15+
```bash
16+
curl -L https://foundry.paradigm.xyz | bash
17+
foundryup
18+
```
19+
20+
## Understanding the Components
21+
22+
The Tangle Liquid Restaking implementation consists of the following key components:
23+
24+
1. **Vault Contract (TangleLiquidRestakingVault)**: An ERC4626-compliant vault that:
25+
- Manages deposits and withdrawals
26+
- Implements reward distribution with index-based accounting
27+
- Handles delegation through the MultiAssetDelegation precompile
28+
- Provides liquid token representation of staked assets
29+
30+
2. **MultiAssetDelegation Wrapper**: Interfaces with Tangle's MultiAssetDelegation precompile at `0x0000000000000000000000000000000000000822`
31+
32+
Core features include:
33+
```solidity
34+
contract TangleLiquidRestakingVault is ERC4626, Owned, TangleMultiAssetDelegationWrapper {
35+
/// @notice Scale factor for reward index calculations
36+
uint256 private constant REWARD_FACTOR = 1e18;
37+
38+
/// @notice Tracks user's reward snapshot for a token
39+
struct RewardSnapshot {
40+
uint256 rewardIndex; // Global index at snapshot creation
41+
uint256 timestamp; // When snapshot was created
42+
uint256 shareBalance; // User's share balance at snapshot
43+
uint256 lastRewardIndex; // Index in rewardTimestamps array
44+
uint256 pendingRewards; // Unclaimed rewards at snapshot
45+
}
46+
47+
/// @notice Operator address for delegation
48+
bytes32 public operator;
49+
50+
/// @notice Blueprint selection for delegation and exposure
51+
uint64[] public blueprintSelection;
52+
}
53+
```
54+
55+
## Step 1: Setting Up the Project
56+
57+
First, clone the reference implementation:
58+
59+
```bash
60+
git clone https://github.com/tangle-network/lrt
61+
cd lrt
62+
forge soldeer update -d
63+
```
64+
65+
## Step 2: Core Implementation Details
66+
67+
### Reward Distribution System
68+
69+
The vault implements a sophisticated reward distribution system using index-based accounting:
70+
71+
```solidity
72+
/// @notice Calculate pending rewards for a user
73+
function _calculatePendingRewards(address user, address token) internal view returns (uint256) {
74+
RewardSnapshot memory snapshot = userSnapshots[user][token];
75+
RewardData storage rData = rewardData[token];
76+
77+
// Calculate rewards since last snapshot
78+
uint256 indexDelta = rData.index - snapshot.rewardIndex;
79+
// Use mulDivUp for final reward calculation to ensure no dust is left behind
80+
uint256 newRewards = snapshot.shareBalance.mulDivUp(indexDelta, REWARD_FACTOR);
81+
uint256 totalRewards = newRewards + snapshot.pendingRewards;
82+
83+
return totalRewards;
84+
}
85+
```
86+
87+
### Delegation Management
88+
89+
The vault handles delegation through the MultiAssetDelegation precompile, managing deposits and withdrawals:
90+
91+
```solidity
92+
/// @notice Deposit assets into vault and delegate
93+
function deposit(uint256 assets, address receiver) public override returns (uint256 shares) {
94+
shares = previewDeposit(assets);
95+
96+
// Process reward snapshots
97+
if (rewardTokens.length > 0) {
98+
_updateAllRewardIndices();
99+
// ... snapshot processing
100+
}
101+
102+
// Complete deposit
103+
super.deposit(assets, receiver);
104+
105+
// Deposit into MADs and delegate
106+
_deposit(assets);
107+
_delegate(operator, assets, blueprintSelection);
108+
109+
return shares;
110+
}
111+
```
112+
113+
## Step 3: Testing the Implementation
114+
115+
Create test files in the `test` directory using Foundry's Solidity testing framework. Here's an example test structure:
116+
117+
```solidity
118+
// SPDX-License-Identifier: UNLICENSED
119+
pragma solidity ^0.8.20;
120+
121+
import "forge-std/Test.sol";
122+
import "../src/TangleLiquidRestakingVault.sol";
123+
124+
contract TangleLiquidRestakingVaultTest is Test {
125+
TangleLiquidRestakingVault vault;
126+
address baseToken;
127+
bytes32 operator;
128+
uint64[] blueprintSelection;
129+
130+
function setUp() public {
131+
// Setup test environment
132+
baseToken = address(new ERC20("Test Token", "TEST"));
133+
operator = bytes32(uint256(1));
134+
blueprintSelection = new uint64[](1);
135+
blueprintSelection[0] = 1;
136+
137+
// Deploy vault
138+
vault = new TangleLiquidRestakingVault(
139+
baseToken,
140+
operator,
141+
blueprintSelection,
142+
MULTI_ASSET_DELEGATION_CONTRACT,
143+
"Liquid Restaked Test",
144+
"lrTEST"
145+
);
146+
}
147+
148+
function testDeposit() public {
149+
uint256 amount = 1000e18;
150+
deal(baseToken, address(this), amount);
151+
152+
ERC20(baseToken).approve(address(vault), amount);
153+
vault.deposit(amount, address(this));
154+
155+
assertEq(vault.balanceOf(address(this)), amount);
156+
}
157+
}
158+
```
159+
160+
Run the tests using Forge:
161+
```bash
162+
forge test -vv
163+
```
164+
165+
## Step 4: Deployment
166+
167+
The vault can be deployed using Forge's deployment capabilities:
168+
169+
1. Create a deployment script in `script/DeployVault.s.sol`:
170+
171+
```solidity
172+
// SPDX-License-Identifier: UNLICENSED
173+
pragma solidity ^0.8.20;
174+
175+
import "forge-std/Script.sol";
176+
import "../src/TangleLiquidRestakingVault.sol";
177+
178+
contract DeployVault is Script {
179+
function run() external {
180+
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
181+
vm.startBroadcast(deployerPrivateKey);
182+
183+
// Deploy vault
184+
bytes32 operator = bytes32(uint256(vm.envUint("OPERATOR_ID")));
185+
uint64[] memory blueprintSelection = new uint64[](1);
186+
blueprintSelection[0] = uint64(vm.envUint("BLUEPRINT_ID"));
187+
188+
TangleLiquidRestakingVault vault = new TangleLiquidRestakingVault(
189+
vm.envAddress("BASE_TOKEN"),
190+
operator,
191+
blueprintSelection,
192+
MULTI_ASSET_DELEGATION_CONTRACT,
193+
"Liquid Restaked Token",
194+
"LRT"
195+
);
196+
197+
vm.stopBroadcast();
198+
}
199+
}
200+
```
201+
202+
2. Configure deployment variables in `.env`:
203+
204+
```env
205+
TANGLE_RPC_URL="https://testnet-rpc.tangle.tools" # or mainnet
206+
PRIVATE_KEY="your-private-key"
207+
BASE_TOKEN="0x..."
208+
OPERATOR_ID="1" # your operator ID
209+
BLUEPRINT_ID="1" # your blueprint ID
210+
```
211+
212+
3. Deploy using Forge:
213+
214+
```bash
215+
forge script script/DeployVault.s.sol:DeployVault --rpc-url $TANGLE_RPC_URL --broadcast
216+
```
217+
218+
## Step 5: Interacting with the Vault
219+
220+
The vault exposes several key functions for user interaction:
221+
222+
### Deposits and Withdrawals
223+
224+
```solidity
225+
/// Schedule unstaking of assets
226+
function scheduleUnstake(uint256 assets) external {
227+
uint256 shares = previewWithdraw(assets);
228+
require(balanceOf[msg.sender] >= shares, "Insufficient shares");
229+
230+
// Track scheduled unstake
231+
scheduledUnstakeAmount[msg.sender] += assets;
232+
233+
// Process snapshots to stop reward accrual
234+
_processRewardSnapshots(msg.sender, address(0), shares);
235+
236+
// Schedule unstake through wrapper
237+
_scheduleUnstake(operator, assets);
238+
}
239+
240+
/// Execute the unstake
241+
function executeUnstake() external {
242+
uint256 scheduled = scheduledUnstakeAmount[msg.sender];
243+
if (scheduled == 0) revert NoScheduledAmount();
244+
245+
// Execute unstake through wrapper
246+
_executeUnstake();
247+
248+
// Update state tracking
249+
unstakeAmount[msg.sender] += scheduled;
250+
scheduledUnstakeAmount[msg.sender] = 0;
251+
}
252+
```
253+
254+
### Reward Management
255+
256+
```solidity
257+
/// Claim rewards for specified tokens
258+
function claimRewards(address user, address[] calldata tokens) external returns (uint256[] memory) {
259+
if (msg.sender != user) revert Unauthorized();
260+
261+
rewards = new uint256[](tokens.length);
262+
_updateAllRewardIndices();
263+
264+
for (uint256 i = 0; i < tokens.length; i++) {
265+
address token = tokens[i];
266+
if (!rewardData[token].isValid) revert InvalidRewardToken();
267+
rewards[i] = _claimReward(user, token);
268+
}
269+
270+
return rewards;
271+
}
272+
```
273+
274+
## Security Considerations
275+
276+
The vault implements several security measures:
277+
278+
1. **Access Control**: Uses Solmate's `Owned` for admin functions
279+
2. **Reward Accounting**: Index-based accounting prevents double-claiming
280+
3. **Withdrawal Process**: Two-step withdrawal process with unstaking period
281+
4. **Math Safety**: Uses `FixedPointMathLib` for safe calculations
282+
283+
Key security features from the contract:
284+
```solidity
285+
/// @notice Scale factor for reward index calculations
286+
uint256 private constant REWARD_FACTOR = 1e18;
287+
288+
/// @notice Uses mulDivUp for final reward calculation
289+
uint256 newRewards = snapshot.shareBalance.mulDivUp(indexDelta, REWARD_FACTOR);
290+
291+
/// @notice Validates withdrawal amounts
292+
if (scheduledWithdrawAmount[owner] < assets) revert NoScheduledAmount();
293+
```
294+
295+
For more information on the MultiAssetDelegation precompile and its features, see the [precompile documentation](../../developers/precompiles/features/multi-asset-delegation.mdx).

0 commit comments

Comments
 (0)