Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 10 additions & 0 deletions astro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ export default defineConfig({
'/itn/upgrade-node': '/nocturne/upgrade-node',
'/operator/guides/archive-node': '/operator/archive-node',
'/operator/guides/provisioner-node': '/operator/provisioner',
'/learn/guides/dusk-mainnet-onramp': '/learn/guides/legacy',
'/learn/guides/bep2-migration': '/learn/guides/legacy',
'/learn/guides/erc20-staking': '/learn/guides/legacy',
'/learn/deep-dive/assets-and-regulations/mica': '/learn/deep-dive/assets-and-regulations',
'/learn/deep-dive/assets-and-regulations/lifecycle': '/learn/deep-dive/assets-and-regulations',
'/learn/deep-dive/assets-and-regulations/dematerialization': '/learn/deep-dive/assets-and-regulations',
'/learn/wallet-terminology': '/learn/glossary',
'/developer/integrations/hashing-algorithms': '/developer/integrations/reference',
'/developer/integrations/addresses': '/developer/integrations/reference',
'/developer/smart-contract/hyperstaking_tech': '/learn/hyperstaking',
},
integrations: [
starlight({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Stake Abstraction
title: Stake Abstraction (Technical Guide)
description: Learn how stake abstraction is implemented on Dusk via Hyperstaking, and how to use it in your smart contracts.
---

Expand Down
36 changes: 36 additions & 0 deletions src/content/docs/developer/integrations/reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: Encoding & Hashing Reference
description: Address encoding and hashing algorithms used by the Dusk protocol.
---

This page collects small protocol references that are useful for integrators and indexers.

## Address format

Dusk wallet addresses are Base58-encoded bytes of compressed public keys.

| Address type | Underlying key(s) | Encoding |
| --- | --- | --- |
| **Moonlight** (public) | 1x `BLS12-381 G2` compressed (96 B) | `Base58` |
| **Phoenix** (shielded) | 2x `Jubjub` points (`A`, `B`) compressed (2 x 32 B) | `Base58` |

If you are building in Rust, the most reliable way to validate/parse addresses is to use `rusk_wallet::Address::from_str()` (it performs Base58 decoding, decompression, and structural checks).

## Hashing algorithms

High-level map of what hashes are used for what (internal details live in `rusk`):

- **SHA3-256**
- Block hashes, Merkle roots, and various consensus-related IDs.
- **BLAKE3**
- Contract bytecode hash and contract event bloom filters.
- **BLAKE2b**
- Contract IDs.
- Transaction IDs and `hash_to_scalar`-style hashing (hashing bytes, then mapping into a BLS scalar).
- **SHA2-256**
- Integrity checks and some key-derivation primitives in the wallet stack.

:::tip[Tip]
If you can, prefer the official SDKs (for example w3sper) instead of re-implementing protocol hashing or encoding.
:::

43 changes: 43 additions & 0 deletions src/content/docs/learn/deep-dive/assets-and-regulations/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: Assets & Regulations
description: Background and references for regulated assets on Dusk.
---

This page is a short, docs-focused overview of common regulatory concepts that show up when building tokenized assets and other regulated flows.

If you're looking for implementation details, start here:
- [Digital Identity Protocol (Citadel)](/developer/digital-identity/protocol)
- [Transaction Models (Moonlight & Phoenix)](/learn/deep-dive/duskds-tx-models)

## MiCA (EU)

MiCA (Markets in Crypto-Assets Regulation) is the EU framework that sets requirements for:
- Crypto-asset issuers (including stablecoin categories like EMTs and ARTs)
- Crypto Asset Service Providers (CASPs)

:::note[Not legal advice]
This is a technical overview for builders. For requirements and interpretation, use official sources and qualified legal advice.
:::

**Official sources**
- ESMA’s MiCA hub: <a href="https://www.esma.europa.eu/esmas-activities/digital-finance-and-innovation/markets-crypto-assets-regulation-mica" target="_blank" rel="noreferrer">ESMA</a>
- Legal text: <a href="https://eur-lex.europa.eu" target="_blank" rel="noreferrer">EUR-Lex</a>

## Practical “Security Token” Lifecycle Requirements

Regardless of jurisdiction, regulated assets often imply a few recurring product requirements:
- **Access control**: only eligible parties can hold/transact (allowlists or identity/credential checks).
- **Transfer checks**: transfers fail with clear reasons, and (ideally) can be simulated/checked pre-flight.
- **Corporate actions**: dividends/coupons, burns, splits, and issuer-driven actions.
- **Recovery & remediation**: processes for lost keys, fraud response, and legally required actions.
- **Governance/voting**: snapshots and vote windows without double-counting.
- **Audit & reporting**: the ability to produce compliant reports without leaking unnecessary user data.

On Dusk, these concerns typically connect to identity/credentials (Citadel), smart contracts, and the dual transaction models (Moonlight for transparent flows and Phoenix for shielded flows).

## Dematerialization and CSDs (Concepts)

Dematerialization is the shift from paper certificates to electronic records of ownership. In traditional finance, Central Securities Depositories (CSDs) and associated market infrastructure manage issuance, custody, and settlement processes.

For many tokenization projects, the relevant takeaway is that “real-world” asset workflows often require more than transfers: role-based controls, recovery paths, and auditability tend to be first-class requirements.

10 changes: 8 additions & 2 deletions src/content/docs/learn/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ Hedger is the evolution of Zedger, built on DuskEVM and powered by fully homomor

#### Hyperstaking

Hyperstaking is a feature that allows smart contracts to manage stakes with custom logic. Similar to "Account Abstraction," it enables use cases like privacy-preserving staking, affiliate programs, delegation, liquid staking, and yield boosting. Staking operations are initiated via a provisioner key, with signature verification only required for the initial stake, offering flexibility and innovation in staking models.
Hyperstaking is stake abstraction: a feature that lets smart contracts participate in staking and manage staking rewards with on-chain logic.

It enables use cases like staking pools, delegated staking services, and other programmable staking patterns. See: [Stake Abstraction](/learn/hyperstaking).

#### Kadcast

Expand Down Expand Up @@ -66,7 +68,11 @@ A shielded account is based on the [Phoenix](#phoenix) UTXO transaction model an

#### Profile

A [profile](/learn/wallet-terminology#profile-and-accounts) is a pairing of a Public Account [Moonlight](#moonlight) and a Shielded Account ([Phoenix](#phoenix) derived from a single mnemonic. Profiles are created in pairs to allow for both public and privacy-preserving transactions.
A profile is a pairing of a [Moonlight](#moonlight) (public) account and a [Phoenix](#phoenix) (shielded) account derived from a single mnemonic.

Wallets use profiles so you can manage both transaction models side-by-side, while keeping keys and addresses organized.

![Wallet hierarchy](../../../assets/wallet_hierarchy.png)

#### RUES

Expand Down
38 changes: 38 additions & 0 deletions src/content/docs/learn/guides/legacy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Legacy Guides (Archived)
description: Legacy programs and guides kept for transparency. These flows are no longer active.
---

This page collects legacy programs and guides that are no longer active.

If you’re looking to move ERC20/BEP20 DUSK to native DUSK today, use: [BEP20/ERC20 Migration](/learn/guides/mainnet-migration/).

## Mainnet Genesis On-Ramp (Ended)

The mainnet genesis on-ramp is closed. These links are kept for reference:

- ERC20 on-ramp contract (Ethereum): <a href="https://etherscan.io/address/0x8787BbE53920B33411F7C9A91Ac321AF1ea1aa2d" target="_blank" rel="noreferrer">0x8787BbE53920B33411F7C9A91Ac321AF1ea1aa2d</a>
- BEP20 on-ramp contract (BSC): <a href="https://bscscan.com/address/0x3886ab688febff60ce21e99251035f8e29abca31" target="_blank" rel="noreferrer">0x3886ab688febff60ce21e99251035f8e29abca31</a>

Genesis on-ramp state snapshots:

- ERC20 snapshot: <a href="https://raw.githubusercontent.com/dusk-network/dusk-migration/refs/heads/genesis-state/genesis-state-eth.toml" target="_blank" rel="noreferrer">genesis-state-eth.toml</a>
- BEP20 snapshot: <a href="https://raw.githubusercontent.com/dusk-network/dusk-migration/refs/heads/genesis-state/genesis-state-bsc.toml" target="_blank" rel="noreferrer">genesis-state-bsc.toml</a>

## BEP2 -> BEP20 Migration (Ended)

The BEP2 to BEP20 DUSK migration concluded on **November 1, 2024**. The migration address is no longer active:

`bnb1dfls6c8y39l7qq4gj2479wkehg85pt5m07y94g`

## Withdraw Staked ERC20 DUSK (ITN2, Legacy)

This only applies if you staked ERC20 DUSK via the ITN2 staking portal (pre-mainnet).

1. Open the staking contract on Etherscan and connect the same wallet address you used to stake:
<a href="https://etherscan.io/address/0x4ab6ffa52460979dde1e442fb95f8bac56c3adc3" target="_blank" rel="noreferrer">0x4ab6ffa52460979dde1e442fb95f8bac56c3adc3</a>
2. In **Read Contract**, call `balanceOf(address)` to find your staked amount.
3. In **Write Contract**, call `withdraw(amount)` with that exact amount.

If you need help recovering funds, ask in the Dusk Discord: <a href="https://discord.gg/dusk-official" target="_blank" rel="noreferrer">discord.gg/dusk-official</a>.

178 changes: 159 additions & 19 deletions src/content/docs/learn/hyperstaking.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,180 @@
---
title: Stake Abstraction
description: Learn how Hyperstaking provides stake abstraction on Dusk, enabling smart contracts to stake DUSK.
description: Stake Abstraction (Hyperstaking) lets smart contracts stake DUSK. This page includes the technical integration guide.
---

# What is Stake Abstraction?
Stake Abstraction (Hyperstaking) lets **smart contracts** participate in staking on Dusk. This enables on-chain staking pools and other programmable staking logic.

Stake Abstraction (Hyperstaking) enables smart contracts to participate in staking on Dusk, replacing the traditional model where only user keys are allowed to stake. This unlocks programmable and decentralized staking, allowing for automated staking pools, delegated staking services, and the creation of staking derivatives. With Hyperstaking, **stake abstraction** becomes a reality.
## When you need it

Hyperstaking works by enabling **smart contracts to act as staking participants**, just like regular users. This means that:
Use stake abstraction if a **contract** needs to own/manage stake and rewards, for example:

- A smart contract can stake and unstake based on predefined logic within the contract.
- Staking rewards earned by the smart contract can be automatically reinvested, distributed, or pooled.
- Liquid staking / staking pools
- Delegated staking services (staking-as-a-service)
- Staking derivatives and automated reward distribution

This stake abstraction not only eliminates the need for manual staking management and the need to run a node to stake, but it also unlocks new staking models that enhances flexibility for both developers and users.
If you are staking as an individual from a wallet, you do not need this page. Use the normal staking flow instead.

## Use cases

Hyperstaking expands the design space for staking on Dusk, creating new ways for users and projects to engage with the network. Key use cases include:
### Liquid staking / staking pools

### Liquid Staking
A contract can accept deposits, stake on behalf of depositors, and distribute (or reinvest) rewards according to its own rules.

Hyperstaking enables **Liquid Staking**, where Smart contracts can operate staking pools, where users delegate funds, and the contract manages the staking process automatically. This means that **users are now able to stake without running their own node**, while automatically collect rewards.
Example: <a href="https://x.com/sozu_dusk" target="_blank" rel="noreferrer">Sozu</a> runs an automated staking pool so users can stake without operating their own node.

<a href="https://x.com/sozu_dusk " target="_blank">Sozu</a> is the first project leveraging Hyperstaking, offering an automated staking pool that allow users to stake `DUSK` without the technical overhead of node operation. By utilizing smart contract staking, Sozu enhances accessibility while maintaining a trustless and decentralized environment.
### Referral / affiliate staking

### Referral-Based Staking
Contracts can implement arbitrary reward-splitting rules (for example: route a portion of rewards to referrers, affiliates, or operators).

Hyperstaking also enables **referral-based staking models**, where users who onboard others into staking earn a share of the staking rewards. This introduces a sustainable incentive structure that fosters network growth and encourages greater decentralization. More information about this upcoming project will be provided soon.
## Protocol-level notes

### Other use cases
- The **minimum stake** requirement applies to contracts too: **1,000 DUSK**.
- Stake is considered active after a maturity period of **4320 blocks (~12 hours)**.
- Reward distribution depends on consensus participation; see [Staking basics](/learn/guides/staking-basics#how-are-rewards-determined).

By providing stake abstraction, Hyperstaking unlocks new business models, including:
## Technical guide (smart contract developers) {#technical-guide}

- **Staking-as-a-service** platforms, where third-party providers facilitate staking for users.
- Custom staking mechanisms, enabling projects to design **staking-based incentives** tailored to their ecosystem.
Stake abstraction requires contracts to interact with the genesis **Stake Contract** (and the **Transfer Contract** for contract-to-contract calls).

In short, the introduction of Hyperstaking on Dusk removes the limitations of traditional staking models and empowers smart contracts to redefine how staking works.
### Reference links

Deep dive into the technicalities of Hyperstaking [here](/developer/smart-contract/hyperstaking_tech)
- Stake contract source:
<a href="https://raw.githubusercontent.com/dusk-network/contracts/main/genesis/stake/src/state.rs" target="_blank" rel="noreferrer">genesis/stake</a>
- Transfer contract source:
<a href="https://raw.githubusercontent.com/dusk-network/contracts/main/genesis/transfer/src/state.rs" target="_blank" rel="noreferrer">genesis/transfer</a>
- Example implementation:
<a href="https://raw.githubusercontent.com/dusk-network/rusk/refs/heads/master/contracts/charlie/src/state.rs" target="_blank" rel="noreferrer">rusk/contracts/charlie</a>

### Required Stake Contract calls

These are called on the Stake Contract:

- `stake_from_contract(recv: ReceiveFromContract)` to stake from a contract.
- `unstake_from_contract(unstake: WithdrawToContract)` to unstake.
- `withdraw_from_contract(withdraw: WithdrawToContract)` to claim rewards.

### Callbacks your contract must implement

Your contract must implement these callbacks (see the example contract above):

- `receive_unstake(receive: ReceiveFromContract)` to receive unstaked funds.
- `receive_reward(receive: ReceiveFromContract)` to receive staking rewards.

### Important: `stake_from_contract` must be triggered via a transfer

Unlike user staking (`stake(stake: Stake)`), contracts cannot call `stake_from_contract` directly.

`stake_from_contract` expects a `ReceiveFromContract` and validates that it is invoked as part of a fund transfer, so the correct pattern is:

1. Move funds into the contract.
2. Perform a `contract_to_contract` transfer to the stake contract, with `fn_name = "stake_from_contract"`.

### Examples (Rust)

<details>
<summary>Stake via <code>contract_to_contract</code></summary>

```rust
pub fn stake(&mut self, stake: Stake) {
let value = stake.value();
let data = rkyv::to_bytes::<_, SCRATCH_BUF_BYTES>(&stake)
.expect("Stake serialization should succeed")
.to_vec();

// 1) Deposit funds into this contract
let _: () = abi::call(TRANSFER_CONTRACT, "deposit", &value)
.expect("Depositing funds into contract should succeed");

// 2) Call `stake_from_contract` via a contract-to-contract transfer
let contract_to_contract = ContractToContract {
contract: STAKE_CONTRACT,
value,
data,
fn_name: "stake_from_contract".into(),
};

let _: () = abi::call(
TRANSFER_CONTRACT,
"contract_to_contract",
&contract_to_contract,
)
.expect("Transferring to stake contract should succeed");
}
```

</details>

<details>
<summary>Unstake + receive callback</summary>

```rust
pub fn unstake(&mut self, unstake: Withdraw) {
let value = unstake.transfer_withdraw().value();
let data =
rkyv::to_bytes::<_, SCRATCH_BUF_BYTES>(unstake.transfer_withdraw())
.expect("Withdraw serialization should succeed")
.to_vec();

let withdraw_to_contract = WithdrawToContract::new(
*unstake.account(),
value,
"receive_unstake",
)
.with_data(data);

let _: () = abi::call(
STAKE_CONTRACT,
"unstake_from_contract",
&withdraw_to_contract,
)
.expect("Unstake from stake contract should succeed");
}

pub fn receive_unstake(&mut self, receive: ReceiveFromContract) {
let withdraw: TransferWithdraw = rkyv::from_bytes(&receive.data)
.expect("Withdraw should deserialize");

let _: () = abi::call(TRANSFER_CONTRACT, "withdraw", &withdraw)
.expect("Withdrawing stake should succeed");
}
```

</details>

<details>
<summary>Withdraw rewards + receive callback</summary>

```rust
pub fn withdraw(&mut self, unstake: Withdraw) {
let value = unstake.transfer_withdraw().value();
let data =
rkyv::to_bytes::<_, SCRATCH_BUF_BYTES>(unstake.transfer_withdraw())
.expect("Withdraw serialization should succeed")
.to_vec();

let withdraw_to_contract = WithdrawToContract::new(
*unstake.account(),
value,
"receive_reward",
)
.with_data(data);

let _: () = abi::call(
STAKE_CONTRACT,
"withdraw_from_contract",
&withdraw_to_contract,
)
.expect("Withdraw rewards from stake contract should succeed");
}

pub fn receive_reward(&mut self, receive: ReceiveFromContract) {
let withdraw: TransferWithdraw = rkyv::from_bytes(&receive.data)
.expect("Withdraw should deserialize");

let _: () = abi::call(TRANSFER_CONTRACT, "withdraw", &withdraw)
.expect("Withdrawing rewards should succeed");
}
```

</details>
20 changes: 1 addition & 19 deletions src/sidebars/defaultSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,7 @@ const defaultSidebar = [
label: "Transaction Models",
link: "learn/deep-dive/duskds-tx-models",
},
{
label: "Assets & Regulations",
items: [
{
label: "MiCA",
link: "learn/deep-dive/assets-and-regulations/mica",
},
{
label: "Security Lifecycle",
link: "learn/deep-dive/assets-and-regulations/lifecycle",
},
{
label: "Security Dematerialization",
link: "learn/deep-dive/assets-and-regulations/dematerialization",
},
],
collapsed: true,
},
{ label: "Wallet Terminology", link: "learn/wallet-terminology" },
{ label: "Assets & Regulations", link: "learn/deep-dive/assets-and-regulations" },
{ label: "Economic Protocol", link: "learn/deep-dive/economic-protocol" },
{ label: "DuskVM", link: "learn/deep-dive/dusk-vm" },
{ label: "DuskEVM", link: "learn/deep-dive/dusk-evm" },
Expand Down
Loading