From 9014ba3d9c5e100535e3cf3dc8195428f950b0f1 Mon Sep 17 00:00:00 2001 From: DHEBP <152355273+DHEBP@users.noreply.github.com> Date: Sun, 7 Jun 2026 21:39:18 -0400 Subject: [PATCH 1/2] docs(dvm): clarify Initialize vs InitializePrivate semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a focused subsection to smart-contract-fundamentals explaining that InitializePrivate flips a single metadata byte (SC_META_DATA.Type 0->1) and selects the install entrypoint — nothing more. It does NOT hide contract code, encrypt state, or change STORE/LOAD/GetSC behavior; for both types, code and stored variables are world-readable. "Private smart contract" refers to tokens becoming encrypted balances in user wallets, not to the contract itself. Grounded in daemon source (dvm/sc.go:38, transaction_execute.go:325-326, :336-337) and cross-linked to the existing private-smart-contracts page. --- .../pages/dvm/smart-contract-fundamentals.mdx | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/derod-main/pages/dvm/smart-contract-fundamentals.mdx b/derod-main/pages/dvm/smart-contract-fundamentals.mdx index 522cad3..e5b5fee 100644 --- a/derod-main/pages/dvm/smart-contract-fundamentals.mdx +++ b/derod-main/pages/dvm/smart-contract-fundamentals.mdx @@ -77,6 +77,52 @@ This looks primitive, but it's **by design**. There is no hidden control flow. Y --- +## `Initialize` vs `InitializePrivate` + +Every contract has exactly one initializer that runs **once**, at install time. It is named **either** `Initialize` **or** `InitializePrivate` — and which name you choose is the *only* difference between the two contract types DERO recognizes. + +```basic +// Type 0 — "Open" contract +Function Initialize() Uint64 + 10 STORE("owner", SIGNER()) + 20 RETURN 0 +End Function + +// Type 1 — "Private" contract: identical body, different name +Function InitializePrivate() Uint64 + 10 STORE("owner", SIGNER()) + 20 RETURN 0 +End Function +``` + +At deploy, the daemon checks the function name and sets a single metadata byte: + +```go +// blockchain/transaction_execute.go:325-326 +if _, ok := sc.Functions["InitializePrivate"]; ok { + meta.Type = 1 // present -> Private (Type 1); absent -> Open (Type 0) +} +// ...then the matching name is used as the install entrypoint: +// transaction_execute.go:336-337 if meta.Type == 1 { entrypoint = "InitializePrivate" } +``` + +That byte is the whole distinction: + +```go +// dvm/sc.go:38 +Type byte // 0 = Open, 1 = Private +``` + + +**`InitializePrivate` does NOT hide your contract.** It does not encrypt code, does not encrypt state, and does not change how `STORE`/`LOAD` or `DERO.GetSC` behave. For **both** types the contract code is public and every stored variable is world-readable — `DERO.GetSC` serves Type 0 and Type 1 state identically, with no privacy gate. + + +So what is "private" about a private smart contract? **The tokens it issues**, not the contract itself. When a contract sends an asset with `SEND_ASSET_TO_ADDRESS`, that balance lands **encrypted in the recipient's wallet** and moves wallet-to-wallet with homomorphic encryption afterward — the contract never tracks who holds what. The Type 1 marker is what tells the chain to treat the contract as a private-asset issuer. (See [Private Smart Contracts](/privacy/private-smart-contracts) for the token model in full.) + +**Practical guidance:** if your contract issues tokens/assets, use `InitializePrivate`. If it is a pure logic or storage contract, either name works — but never rely on either one to keep state secret. Anything that must be confidential has to be encrypted by your app **before** it is stored on-chain. + +--- + ## The Core Primitives Everything in DVM-BASIC is built from a handful of building blocks: From 35a72c82231f72586850ebb2db6627245947520e Mon Sep 17 00:00:00 2001 From: DHEBP <152355273+DHEBP@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:28:32 -0400 Subject: [PATCH 2/2] docs(wallet-rpc): note payload-bearing transfers need a non-zero amount Extends the transfer 'amount' NOTE: a zero-amount transfer creates no output for the recipient's wallet to detect, so an attached payload_rpc (comment, destination port, or app data) never arrives even though the tx is valid and mined. Use >= 1 atomic unit. Applies to any use of a transfer as a data carrier, not just payments. Confirmed against the DeroMessage mainnet reference (Amount=1). --- derod-main/pages/rpc-api/wallet-rpc-api.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/derod-main/pages/rpc-api/wallet-rpc-api.mdx b/derod-main/pages/rpc-api/wallet-rpc-api.mdx index 9173705..51777bc 100644 --- a/derod-main/pages/rpc-api/wallet-rpc-api.mdx +++ b/derod-main/pages/rpc-api/wallet-rpc-api.mdx @@ -182,7 +182,7 @@ curl -X POST \ } ``` -**NOTE:** The amount is in atomic format. As a reminder, 10^5 (=100000) is equivalent to 1 DERO. +**NOTE:** The amount is in atomic format. As a reminder, 10^5 (=100000) is equivalent to 1 DERO. When using a transfer to carry a payload (a comment, destination port, or app data) rather than to send value, the amount must still be at least **1 atomic unit** (`0.00001 DERO`): a zero-amount transfer creates no output for the recipient's wallet to detect, so its attached `payload_rpc` never reaches them even though the transaction is valid and mined. This applies to any use of a transfer as a data carrier, not just payments. If this address is not registered on the blockchain, you will get this error: