HCS‑16 Standard: Floras - AppNet Accounts
Status: Draft
Version: 1.0
Table of Contents
- Authors
- Abstract
- Motivation
- Terminology
- Specification
5.1. Prerequisites
5.2. Flora Account Creation
5.3. Flora Topics
5.4. Profile Schema
5.5. Message Protocol
5.6. Lifecycle Flows
5.7. Reference Implementation - Security Considerations
- Versioning & Upgrades
- References
- Change Log
Authors
- Patches https://twitter.com/tmcc_patches
- Kantorcodes https://twitter.com/kantorcodes
Abstract
HCS‑16 defines Flora accounts: multi-signature coordination accounts for decentralized AppNets on Hiero. A Flora extends the HCS‑15 Petal account concept to groups of 2+ independent accounts that jointly control assets, maintain shared state, and coordinate actions through consensus.
Key Components
A Flora account consists of:
- Multisig Account – A Hiero account controlled by a threshold key (T-of-M) composed of member Petal public keys
- Three Mandatory HCS Topics:
- Communication Topic (CTopic) – Coordination, governance, and member chat
- Transaction Topic (TTopic) – Scheduled transaction proposals and approvals
- State Topic (STopic) – State commitments and membership changes
- HCS‑11 Profile – Standardized metadata describing members, thresholds, topics, and policies
What This Standard Defines
- Canonical JSON schema for Flora metadata and messages
- Complete lifecycle flows: creation, operation, membership changes, and dissolution
- Security parameters for threshold selection, membership management, and data availability
- Integration with HCS‑10 (messaging), HCS‑11 (profiles), HCS‑15 (Petals), and HCS‑17 (state attestation)
Motivation
The Challenge
Modern autonomous agents and decentralized applications require multi-party coordination primitives:
- AI Agent Collectives – Multiple AI agents pooling resources for shared tasks
- Escrow Wallets – Trusted intermediaries for marketplace transactions
- Joint Ventures – Temporary business collaborations with shared treasury
- Working Groups – Project-based teams with collective decision-making
- Federated Services – Distributed systems requiring consensus
Current Limitations:
- Manual multisig deployment is error-prone and expensive
- Custom smart contracts require audit overhead and lack standardization
- No native discovery mechanism for finding or joining multi-party accounts
- Poor tooling integration across different implementations
The HCS‑16 Solution
Flora accounts solve these challenges through four core principles:
1. Native Multisig
Uses Hiero's built-in ThresholdKey directly - no Solidity bridges, no custom bytecode, minimal gas costs, reduced audit surface.
2. Structured Communication
Three dedicated HCS topics provide clear separation of concerns:
- CTopic – Human-readable coordination and governance
- TTopic – Machine-parseable transaction proposals
- STopic – Cryptographic state commitments
3. Standards Composability
Flora members are HCS‑15 Petal accounts, so existing tooling works unchanged:
- Profile resolution via HCS‑11
- Messaging via HCS‑10
- State attestation via HCS‑17
4. Discoverability & Negotiation
Flora formation can leverage HCS‑10 channels, making multi-party coordination accessible to autonomous agents.
Terminology
| Term | Definition |
|---|---|
| Flora | The multisig account created under HCS‑16; a decentralized AppNet coordination account |
| Petal | An HCS‑15 account that shares a private key with its Base account |
| Member | A Petal account that participates in a Flora |
| Base Account | The original Hiero account from which a Petal derives its key material |
| Threshold Key (T/M) | A cryptographic key requiring T valid signatures out of M total member keys |
| CTopic | Communication Topic – Human/agent coordination, governance, and general messaging |
| TTopic | Transaction Topic – Scheduled transaction proposals and approval messaging + tracking |
| STopic | State Topic – State commitments, membership changes, and epoch transitions |
| Operator ID | Identifier format <signerAccountId>@<floraAccountId> used to attribute actions to specific members |
| Epoch | Monotonically increasing counter marking state transitions or membership changes |
Specification
Prerequisites
Member Requirements
A Flora MUST be composed of ≥ 2 Petal accounts, where each member:
-
Has a valid HCS‑11 Petal profile including:
-
Uses ECDSA/secp256k1 key cryptography:
- Required for future encryption capabilities
- ED25519 keys are NOT supported (they lack encryption support)
- Key must be accessible for signing Flora transactions
-
Has sufficient HBAR balance for:
- Topic message submissions (≈$0.0001 per message)
- Transaction fees (account creation, topic creation)
- Initial Flora funding contribution (if agreed upon by members)
- Ongoing operational costs
Pre-Formation Considerations
Before creating a Flora, prospective members SHOULD establish consensus on:
-
Governance Parameters:
- Threshold value
T(signatures required for execution) - Total members
M(must be ≥ 2) - Membership change policies (who can propose, voting requirements)
- Transaction approval requirements (all, majority, threshold)
- Threshold value
-
Financial Terms:
- Initial Flora account balance (recommended ≥ 20 HBAR)
- Who funds the initial account creation
- How operational costs are shared
- Treasury management policies
-
Communication Channels:
- Optional pre-negotiation via HCS‑10 inbound topics
- Discovery via HCS‑18 (when implemented)
- Any additional external communication methods members make outside of Flora topics
-
Topic Configuration:
- Whether to implement HIP-991 custom fees on topics
- Fee amounts (if applicable) for spam prevention
- Transaction memo format preferences
- Custom topic requirements beyond the three mandatory topics
Flora / AppNet Account Creation
Flora creation follows a 6-step process that transforms independent Petal accounts into a coordinated multi-signature entity:
Step 1: Decentralized Discovery (Optional)
Pre-formation negotiation can occur using HCS‑10 inbound topics for private negotiation:
- Discovery Method: Use
announce/propose/respondmessages - Proposer Actions: References candidate announcements; candidates accept or reject
- Output: Agreed upon
memberAccounts,threshold(TofM), and funding expectations
Alternative: Members may negotiate off-chain via traditional communication channels or discover via HCS‑18 (when implemented).
Step 2: Key Assembly
After members and details are finalized, construct the Flora's cryptographic foundation:
- Collect each member's public key (ECDSA/secp256k1)
- Create a
KeyListcontaining all member public keys - Set the
thresholdvalue (Tsignatures required) - Verify all members can access their private keys for signing
Example (TypeScript):
const keyList = new KeyList();
keyList.setThreshold(threshold); // e.g., 2 for 2-of-3
for (const member of members) {
keyList.add(member.pubKey);
}
Step 3: Flora Account Creation
The proposer (or designated initiator) submits an AccountCreateTransaction:
Required Parameters:
key = KeyList(threshold, [PubKey1, PubKey2, ...])– The T-of-M threshold keymaxAutomaticTokenAssociations = -1– Recommended for flexibilityinitialBalance = 20 HBAR– Funded by proposer (adjustable based on agreement)
Result: Hiero network returns the new Flora account ID (e.g., 0.0.777)
Step 4: Topic Creation
Immediately after Flora account creation, create three TopicCreateTransactions:
| Topic Type | Enum | Purpose | Admin Key | Submit Key | Memo Format |
|---|---|---|---|---|---|
| Communication | 0 | Coordination & governance | T/M KeyList | 1/M KeyList | hcs-16:0.0.777:0 |
| Transaction | 1 | Scheduled transaction proposals | T/M KeyList | 1/M KeyList | hcs-16:0.0.777:1 |
| State | 2 | State commitments & membership | T/M KeyList | 1/M KeyList | hcs-16:0.0.777:2 |
Key Configuration:
adminKey– Set to Flora's T/M threshold key (requires T signatures to modify topic)submitKey– Set to 1/M threshold (allows any single member to post messages)
Why 1/M for submitKey? Enables any member to post messages without requiring threshold signatures for routine communication.
Step 5: Profile Publication
Create and publish the Flora's HCS‑11 profile:
-
Prepare Profile JSON with:
type: 3(Flora profile type)membersarray (account IDs of all Petal members)thresholdvaluetopicsobject (CTopic, TTopic, STopic IDs)policies(optional governance rules)
-
Upload Profile to:
- HCS topic (via HCS‑1), or
- IPFS/Arweave for persistent storage
-
Set Flora Account Memo to reference the profile:
hcs-11:<resourceLocator>Example:
hcs-11:hcs://1/0.0.789103
Step 6: Member Acknowledgement
Each member confirms Flora activation by posting to CTopic:
Acknowledgement Message:
{
"p": "hcs-16",
"op": "flora_created",
"flora_account_id": "0.0.777",
"topics": {
"communication": "0.0.888",
"transaction": "0.0.889",
"state": "0.0.890"
},
"m": "Member acknowledgement"
}
Activation Criteria: Flora is considered Active when:
- Super-majority (
≥T) of members publishflora_createdmessage to CTopic, OR - Members post initial state to STopic using HCS‑17
state_hashformat
Transaction Memo: hcs-16:op:0:0
Internal Flora Topics
Flora accounts utilize three mandatory HCS topics for structured coordination:
| Topic | Purpose | Required | Topic Memo | Topic Type Enum | Message Protocol |
|---|---|---|---|---|---|
| Communication Topic (CTopic) | Human / agent chat, off‑chain URL exchange, policy proposals, general communications. Future standards are planned to define task coordination. | ✅ | hcs-16:${floraId}:0 | 0 | HCS-16 |
| Transaction Topic (TTopic) | Broadcast of pre‑signed ScheduledTxn IDs, token association proposals, contract calls. | ✅ | hcs-16:${floraId}:1 | 1 | HCS-16 |
| State Topic (STopic) | Flora shared state that is needed for the Flora's purpose. State hash publications per HCS-17, membership attestations, epoch transitions. Required for valid Floras even if not utilized initially. | ✅ | hcs-16:${floraId}:2 | 2 | HCS-17 |
Topic Configuration Rules
Admin Key: All three topics SHOULD share the exact same adminKey as the Flora's account key (T/M threshold). This ensures:
- Topic modifications require consensus (T signatures)
- Topics cannot be unilaterally changed by a single member
- Consistent security model across Flora infrastructure
Submit Key: All topics SHOULD use 1/M keylist threshold to allow each member to submit independently. This enables:
- Any member can post messages without waiting for others
- Asynchronous communication and proposal submission
- Efficient day-to-day operations
HIP-991 Custom Fees (Optional): Custom fees can be added to require HBAR or custom fungible token/NFT to submit messages. This:
- Provides spam prevention mechanism
- Creates economic incentives for thoughtful participation
- Must be agreed upon before Flora creation
Topic Memo Format (Canonical)
hcs-16:<flora_account_id>:<type>
Components:
hcs-16– Protocol identifier<flora_account_id>– The Flora account ID (e.g.,0.0.777)<type>– Topic type enum:0= Communication,1= Transaction,2= State
Examples:
hcs-16:0.0.777:0 // Communication Topic for Flora 0.0.777
hcs-16:0.0.777:1 // Transaction Topic for Flora 0.0.777
hcs-16:0.0.777:2 // State Topic for Flora 0.0.777
Flora / AppNet Account Memo Structure
Flora accounts use the HCS‑11 memo convention to reference their profile document. See HCS‑11 for the canonical grammar and examples.
Memo Format (delegated to HCS‑11):
hcs-11:<resource>
Where <resource> can be:
- HCS HRL:
hcs://<standard>/<topicId>(e.g.,hcs://1/0.0.789103) - IPFS:
ipfs://QmT5NvUtoM5nWFfrQdVrFtvGfKFmG7AHE8P34isapyhCxX - Arweave:
ar://TQGxHPLpUcH7NG6rUYkzEnwD8_WqYQNPIoX5-0OoRXA - HTTPS:
https://example.com/flora-profile.json
This approach provides flexibility in choosing the most appropriate storage mechanism for Flora metadata while maintaining a consistent reference pattern.
Profile Schema
Flora accounts extend the canonical HCS‑11 profile schema. Refer to that standard for the authoritative definition of required fields such as type, members, threshold, and topics, as well as storage guidance.
Key Requirements:
- Flora account memos MUST reference an HCS‑11-compliant profile document
- Profile MUST set
type: 3(Flora profile type) - Flora account SHALL expose valid HCS‑10 inbound and outbound topics for coordination
- Profile SHOULD include
policiesobject for governance rules
Example Profile Snippet
{
"version": "1.0",
"display_name": "🪷 AppNet #3",
"type": 3,
"members": [
{ "accountId": "0.0.1234" },
{ "accountId": "0.0.2345" },
{ "accountId": "0.0.3456" }
],
"threshold": 2,
"topics": {
"communication": "0.0.481516",
"transaction": "0.0.481517",
"state": "0.0.481518",
"custom": [
{
"name": "offChainHashes",
"topicId": "0.0.792894",
"description": "Used for attestation of offchain software"
}
]
},
"policies": {
"membershipChange": "2/3",
"scheduleTxApproval": "all"
}
}
Field Explanations:
members– Array of Petal account IDs participating in this Florathreshold– Number of signatures required (T in T/M)topics.communication– CTopic ID for coordinationtopics.transaction– TTopic ID for scheduled transactionstopics.state– STopic ID for state commitmentstopics.custom– Optional additional topics for specialized purposespolicies– Governance rules for operations (format is implementation-defined)
Message Protocol
All Flora protocol messages follow a standardized envelope format and operation structure.
Protocol Operations
| Enum | op (operation) | Direction | Purpose | Protocol | Required Keys |
|---|---|---|---|---|---|
| 0 | flora_created | CTopic | Publish final Flora account & topic IDs. | HCS-16 | flora_account_id, topics |
| 1 | transaction | TTopic | Propose a Scheduled Transaction for approval. | HCS-16 | operator_id, schedule_id, data?, m? |
| 2 | state_update | STopic | Commit state hash (simple format) | HCS-16 | hash, epoch? |
| 3 | flora_join_request | CTopic | Post proxy of an external join request. | HCS-16 | account_id, connection_request_id, connection_topic_id, connection_seq |
| 4 | flora_join_vote | CTopic | Member vote on a join request. | HCS-16 | account_id, approve, operator_id, connection_request_id, connection_seq |
| 5 | flora_join_accepted | STopic | Confirmed membership change. | HCS-16 | members, epoch |
| 6 | state_hash | STopic | Commit state hash (HCS-17 standardized) | HCS-17 | state_hash, topics, account_id, epoch? |
Notes:
- State Publications: Flora STopics can use either HCS-16
state_updateor HCS‑17state_hashformat - HCS-17 Benefits: The HCS-17 format provides standardized hash calculation, topic list verification, and composite state support
- Protocol Mixing: STopic can receive both HCS-16 operations (2, 5) and HCS-17 operations (
state_hash) - All operations follow their respective protocol's envelope structure
Envelope & Memos
Canonical Message Envelope:
{
"p": "hcs-16",
"op": "<op>",
"operator_id": "<signerAccountId>@<floraAccountId>",
"m": "optional"
}
Field Descriptions:
p– Protocol identifier, always"hcs-16"op– Operation type (see Operations table above)operator_id– Identity of the acting member in format<signerAccountId>@<floraAccountId>m– Optional human-readable memo for context
Transaction Memo Format (Recommended)
When executing transactions from the Flora account, it is RECOMMENDED to include a memo in this format for decentralized analytics and easier auditability of AppNet actions:
Memo Template:
hcs-16:op:<operationEnum>:<topicType>
Components:
hcs-16– Protocol identifierop– Indicates this is an operation memo<operationEnum>– Numeric operation type (0-5, see table above)<topicType>– Topic type enum:0= CTopic,1= TTopic,2= STopic
Examples:
hcs-16:op:0:0 // flora_created on CTopic
hcs-16:op:1:1 // transaction on TTopic
hcs-16:op:2:2 // state_update on STopic
hcs-16:op:3:0 // flora_join_request on CTopic
hcs-16:op:4:0 // flora_join_vote on CTopic
hcs-16:op:5:2 // flora_join_accepted on STopic
hcs-17:op:6:2 // state_hash on STopic
This standardized memo format enables:
- Automated indexing and analytics of Flora operations
- Network-wide monitoring of AppNet activity
- Efficient filtering of Flora-related transactions
- Debugging and audit trail reconstruction
Operation Methods
Transaction (TTopic)
Proposes a scheduled transaction that requires member approval before execution.
Message Shape:
{
"p": "hcs-16",
"op": "transaction",
"operator_id": "0.0.123@0.0.777",
"schedule_id": "0.0.999",
"data": "Swap 1 HBAR for 10 XYZ",
"m": "optional"
}
Fields:
| Field | Description | Type | Required |
|---|---|---|---|
operator_id | Signer account ID with Flora account ID combined by @: <signerAccountId>@<floraAccountId> | string | Yes |
schedule_id | Hedera ScheduleId entity ID (e.g., 0.0.12345) | string | Yes |
data | Human description or helpful data or reference to data (HRL/URL) | string | No |
m | Optional memo for analytics/traceability | string | No |
Transaction Memo: hcs-16:op:1:1
Usage Pattern:
- Member creates a
ScheduleCreateTransactionon Hiero network for desired execution from Flora account - Member posts
transactionoperation to TTopic with schedule ID of the new transaction - Other members review the transaction details
- Members sign the scheduled transaction via
ScheduleSignTransaction - Transaction executes automatically when threshold (T) signatures reached
Flora Created (CTopic)
Announces the successful creation of a Flora and its associated topics. Each member posts this message during Flora activation.
Message Shape:
{
"p": "hcs-16",
"op": "flora_created",
"flora_account_id": "0.0.777",
"topics": {
"communication": "0.0.888",
"transaction": "0.0.889",
"state": "0.0.890"
},
"m": "optional"
}
Fields:
| Field | Description | Type | Required |
|---|---|---|---|
flora_account_id | Newly created Flora account ID | string | Yes |
topics | The three Flora topics | object | Yes |
m | Optional memo | string | No |
Transaction Memo: hcs-16:op:0:0
Purpose:
- Confirms member participation in the Flora
- Provides public record of Flora infrastructure
- Establishes consensus on topic IDs
State Update (STopic)
Commits a new state hash to the State Topic. Flora implementations can choose between HCS-16 simple format or HCS‑17 standardized format.
Option 1: HCS-17 State Hash Format
Message Shape:
{
"p": "hcs-17",
"op": "state_hash",
"state_hash": "<hex-encoded-sha384-hash>",
"topics": ["0.0.888", "0.0.889", "0.0.890"],
"account_id": "0.0.777",
"epoch": 12,
"m": "Flora composite state update"
}
Fields: See HCS‑17 Message Protocol for complete field definitions.
Transaction Memo: hcs-16:op:2:2
Benefits:
- Standardized state hash computation per HCS-17 methodology
- Inter-standard compatibility across HCS ecosystem
- Includes topic list for verification
- Built-in support for composite state hashes (Flora/Bloom)
- Consistent epoch management
- Deterministic calculation enables independent verification
Use When: You need standardized state verification, composite state aggregation, or interoperability with other HCS standards.
Option 2: HCS-16 State Update (Simple)
Message Shape:
{
"p": "hcs-16",
"op": "state_update",
"hash": "<stateHash>",
"epoch": 12,
"timestamp": "2025-09-15T12:00:00.000Z",
"m": "optional"
}
Fields:
| Field | Description | Type | Required |
|---|---|---|---|
hash | State hash (application-defined format) | string | Yes |
epoch | Monotonically increasing counter | number | No |
timestamp | ISO‑8601 timestamp | string | No |
m | Optional memo | string | No |
Transaction Memo: hcs-16:op:2:2
Benefits:
- Simpler format for straightforward use cases
- Application-defined hash calculation
- Fewer required fields
Use When: You have simple state requirements and don't need standardized hash calculation or composite state aggregation.
Join Request (CTopic)
A proxy message posted to the CTopic by a Flora's intake automation or member, representing an external Petal's request to join the Flora.
Message Shape:
{
"p": "hcs-16",
"op": "flora_join_request",
"account_id": "0.0.999",
"connection_request_id": 51234,
"connection_topic_id": "0.0.912345",
"connection_seq": 27,
"m": "This account reached out and requested to join"
}
Fields:
| Field | Description | Type | Required |
|---|---|---|---|
account_id | The account requesting admission. Members use this to look up the candidate's HCS-11 profile. | string | Yes |
connection_request_id | Sequence number of the HCS-10 connection_request on the Flora's inbound topic. | number | Yes |
connection_topic_id | The HCS-10 connection topic ID for this join request. | string | Yes |
connection_seq | Sequence number of the HCS-10 message on the connection topic containing the full join proposal. | number | Yes |
m | Optional purpose/memo. | string | No |
Transaction Memo: hcs-16:op:3:0
Workflow Context:
- External Petal sends
connection_requestto Flora's HCS-10 inbound topic - Intake automation (or member) detects the request
- Automation posts
flora_join_requestproxy to CTopic with references - Members retrieve full proposal from connection topic using
connection_seq - Members vote using
flora_join_voteoperation
Join Vote (CTopic)
Members cast votes on a flora_join_request. The vote references the specific request via HCS-10 sequence numbers to avoid ambiguity.
Message Shape:
{
"p": "hcs-16",
"op": "flora_join_vote",
"account_id": "0.0.999",
"approve": true,
"operator_id": "0.0.123@0.0.777",
"connection_request_id": 51234,
"connection_seq": 27,
"m": "optional"
}
Fields:
| Field | Description | Type | Required |
|---|---|---|---|
account_id | Candidate under vote. | string | Yes |
approve | Boolean decision (true = approve, false = reject). | boolean | Yes |
operator_id | Voting member (<memberId>@<floraId>). | string | Yes |
connection_request_id | The connection_request_id from the corresponding flora_join_request. | number | Yes |
connection_seq | The connection_seq from the corresponding flora_join_request. | number | Yes |
m | Optional memo. | string | No |
Transaction Memo: hcs-16:op:4:0
Voting Rules:
- Each member casts one vote per join request
- Vote is recorded on CTopic for transparency
- Threshold (T) of
approve: truevotes required for acceptance - Members can change their vote by posting a new
flora_join_votemessage - Final acceptance requires executing KeyList update transaction
Join Accepted (STopic)
Confirms a successful membership change by posting the updated member list and incrementing the epoch counter.
Message Shape:
{
"p": "hcs-16",
"op": "flora_join_accepted",
"members": [
"0.0.123",
"0.0.456",
"0.0.999"
],
"epoch": 13,
"m": "optional"
}
Fields:
| Field | Description | Type | Required |
|---|---|---|---|
members | Full updated members list | string[] | Yes |
epoch | Incremented state counter | number | Yes |
m | Optional memo | string | No |
Transaction Memo: hcs-16:op:5:2
Purpose:
- Provides canonical record of current membership
- Enables state synchronization across members
- Marks transition point in Flora history
- Used for reconstructing Flora state from topic history
Protocol Message Examples
Flora Activated — CTopic:
{
"p": "hcs-16",
"op": "flora_created",
"flora_account_id": "0.0.777",
"topics": {
"communication": "0.0.888",
"transaction": "0.0.889",
"state": "0.0.890"
}
}
Share a Scheduled Swap — TTopic:
{
"p": "hcs-16",
"op": "transaction",
"operator_id": "0.0.123@0.0.777",
"schedule_id": "0.0.999",
"data": "Swap 1 HBAR for 10 XYZ"
}
Member Commit State Hash — STopic (HCS-17 format):
{
"p": "hcs-17",
"op": "state_hash",
"state_hash": "a3f5b8c2d1e74f9a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a",
"topics": ["0.0.888", "0.0.889", "0.0.890"],
"account_id": "0.0.777",
"epoch": 12
}
External Petal Join — Internal CTopic Message:
{
"p": "hcs-16",
"op": "flora_join_request",
"account_id": "0.0.999",
"connection_request_id": 51234,
"connection_topic_id": "0.0.912345",
"connection_seq": 27,
"m": "Account 0.0.999 is requesting to join and would like to co‑fund 400 hbar to join"
}
Flora Creation — Sequence Diagram
Lifecycle Flows
JSON Envelope Conventions
Every lifecycle message is valid UTF‑8 JSON and MUST include:
p:"hcs-16"— Protocol identifierop— Operation type (see Operations table)operator_id— Format:<signatureKeyAccountId>@<floraAccountId>for members; or<callerAccountId>for external join requestsm— Optional human‑readable memo
Additional Requirements:
- All timestamps SHOULD use ISO-8601 format.
- All topic IDs MUST use standard Hiero format (
0.0.x) - JSON MUST be valid and parseable
- String fields SHOULD be UTF-8 encoded
Example Lifecycle Messages
Step 1: After Members Create the Flora
{
"p": "hcs-16",
"op": "flora_created",
"flora_account_id": "0.0.777",
"topics": {
"communication": "0.0.888",
"transaction": "0.0.889",
"state": "0.0.890"
}
}
Step 2: Initial State Commitment (HCS-17 format)
{
"p": "hcs-17",
"op": "state_hash",
"state_hash": "48b6c9d2e1f8a3b5c7d9e2f4a6b8c0d2e4f6a8b0c2d4e6f8a0b2c4d6e8f0a2b4c6d8e0f2a4b6c8d0e2f4a6b8c0d2e4f6a8b0c2d4e6f8a0b2c4d6e8f0a2b4",
"topics": ["0.0.888", "0.0.889", "0.0.890"],
"account_id": "0.0.777",
"epoch": 0
}
Creation (Happy Path)
The standard Flora creation flow consists of three main phases:
1. Formation (HCS‑16)
Execute account & topic creation transactions on‑chain:
- Create Flora multisig account with T/M threshold key
- Create three mandatory topics (CTopic, TTopic, STopic)
- Upload and reference HCS‑11 profile
- Set Flora account memo to profile reference
2. Member Acknowledgement
Publish flora_created to CTopic:
- Each member posts
flora_createdmessage - Message includes Flora account ID and topic IDs
- Confirms member awareness and acceptance
- Provides public record of Flora infrastructure
3. Initial State Publication
Publish initial state on STopic:
- Prefer HCS‑17
state_hashformat - Alternative: use HCS‑16
state_updateoperation - Establishes initial epoch (epoch 0 or 1)
- Enables state synchronization across members
Flora Activation: Flora is considered ACTIVE when super-majority (≥T) of members complete Step 2 or 3.
Security Notes
Key List Consistency
Before acceptance, members SHOULD verify:
- The KeyList contains correct public keys for all members
- Threshold value matches agreed-upon value
- No unauthorized keys have been added
- Transaction hash matches expected format
Resource Quota
The initiating member should supply enough ℏ for:
AccountCreateTransaction(≈0.10 HBAR)- Three
TopicCreateTransactions (≈0.01 HBAR each) - Initial Flora account balance (recommended ≥20 HBAR)
- Profile publication costs (if using HCS-1)
Sybil Resistance
Applications MAY impose additional requirements:
- Allow-list of approved Petal accounts
- Proof-of-work challenges
- Required payments (HBAR or fungible tokens) for
flora_join_request - Reputation scores or stake requirements
- Rate limiting on join requests
Membership Change
Add Member
To add a new member to a Flora:
Step 1: Voting Phase (if required)
- New candidate sends
connection_requestto Flora's or a members HCS-10 inbound topic - Intake automation posts
flora_join_requestto CTopic - Members cast votes using
flora_join_voteoperation - Track votes until threshold (≥T) reached
Step 2: KeyList Update Transaction
- Any member posts
transactionoperation to TTopic with:schedule_idreferencing aScheduleCreateTransactiondatafield containing rationale (e.g., "Adding member 0.0.999 per vote")
- The scheduled transaction MUST contain:
AccountUpdateTransactionfor Flora account- Updated KeyList including new member's public key
- Optionally updated threshold value (if agreed upon)
Step 3: Member Signing
- Members sign the scheduled transaction via
ScheduleSignTransaction - Execution occurs automatically when ≥T signatures collected
- Network updates Flora account KeyList
Step 4: State Commitment
- Member posts
flora_join_acceptedto STopic with:- Updated
membersarray - Incremented
epochvalue
- Updated
- Update Flora profile (HCS-11) to reflect new membership
Transaction Memo: hcs-16:op:1:1 (for KeyList update transaction)
Remove Member
Removing a member follows the same process as adding:
Key Differences:
- KeyList update removes the member's public key
- Threshold may need adjustment (ensure T ≤ remaining members)
flora_join_acceptedSHOULD still be posted to mark the transition- Consider updating topic submit keys if member should lose access
Security Consideration: Removing a malicious member is itself a multisig transaction. For critical Floras, set membershipChange policy to require T+1 signatures where feasible.
Dissolution
To permanently delete a Flora:
Pre-Dissolution Checklist:
- Asset Drainage – Transfer all HBAR and tokens out of Flora account
- Token Dissociation – Dissociate all tokens from Flora account
- Topic Cleanup – Optionally delete or transfer admin keys for topics
- Final State Commit – Post final state to STopic for historical record
- Member Coordination – Confirm all members agree on dissolution
Deletion Process:
Step 1: Coordinate on CTopic/TTopic
- Members discuss and confirm dissolution plan
- Agree on asset distribution
- Execute all necessary cleanup transactions
Step 2: Post Deletion Transaction
- Member posts
transactionoperation to TTopic with:schedule_idreferencingScheduleCreateTransactiondatafield: "Flora dissolution per member agreement"
- Scheduled transaction contains
AccountDeleteTransaction
Step 3: Member Signing
- Members sign scheduled transaction
- Execution occurs when signatures reach ≥T
Step 4: Network Execution
- Hiero network deletes Flora account
- Remaining balance (if any) transferred to beneficiary account
- Flora account becomes permanently inaccessible
Read-Only State: If at any time active members fall below T, the Flora becomes Read-Only until membership is restored. This means:
- No transactions can execute (insufficient signatures)
- Topic messages can still be posted (1/M submit key)
- Account balance remains but is inaccessible
- Recovery requires adding new members (which itself requires ≥T signatures from existing members)
Important: Hiero requires all token associations and assets be cleared before account deletion. The deletion transaction will fail if:
- Account holds any fungible tokens
- Account holds any NFTs
- Account has active token associations
- Account has scheduled transactions pending
Reference Implementation
Below is an abridged TypeScript example that assembles a 2‑of‑3 Flora. Error handling removed for brevity.
import {
AccountCreateTransaction,
KeyList,
Hbar,
TopicCreateTransaction,
TopicId,
Client,
AccountId,
PublicKey
} from "@hashgraph/sdk";
// Define member structure
type Member = {
accountId: AccountId;
pubKey: PublicKey;
};
// Configuration
const members: Member[] = await fetchMemberInfo(); // Retrieve from HCS-11 profiles
const threshold = 2; // 2-of-3 signatures required
const client = Client.forTestnet(); // Or mainnet
// Step 1a: Build Flora KeyList (T/M threshold)
const keyList = new KeyList();
keyList.setThreshold(threshold);
for (const m of members) {
keyList.add(m.pubKey);
}
// Step 1b: Build Submit KeyList (1/M threshold for topics)
const submitKeyList = new KeyList();
submitKeyList.setThreshold(1);
for (const m of members) {
submitKeyList.add(m.pubKey);
}
// Step 2: Create the Flora account
const floraReceipt = await new AccountCreateTransaction()
.setKey(keyList)
.setInitialBalance(new Hbar(20))
.setMaxAutomaticTokenAssociations(-1)
.execute(client)
.then((tx) => tx.getReceipt(client));
const floraId = floraReceipt.accountId!;
console.log(`Flora account created: ${floraId}`);
// Step 3: Create the three mandatory topics
const [cTopicId, tTopicId, sTopicId] = await Promise.all([
createTopic(`hcs-16:${floraId}:0`, keyList, submitKeyList), // CTopic
createTopic(`hcs-16:${floraId}:1`, keyList, submitKeyList), // TTopic
createTopic(`hcs-16:${floraId}:2`, keyList, submitKeyList), // STopic
]);
console.log(`Topics created:
CTopic: ${cTopicId}
TTopic: ${tTopicId}
STopic: ${sTopicId}
`);
// Step 4: Create and upload Flora profile (HCS-11)
const profile = {
version: "1.0",
display_name: "Example Flora",
type: 3,
members: members.map(m => ({ accountId: m.accountId.toString() })),
threshold: threshold,
topics: {
communication: cTopicId.toString(),
transaction: tTopicId.toString(),
state: sTopicId.toString()
},
policies: {
membershipChange: "2/3",
scheduleTxApproval: "threshold"
}
};
// Upload profile using HCS-1 (implementation not shown)
const profileTopicId = await uploadProfileToHCS1(profile);
// Step 5: Update Flora account memo
await new AccountUpdateTransaction()
.setAccountId(floraId)
.setAccountMemo(`hcs-11:hcs://1/${profileTopicId}`)
.execute(client)
.then((tx) => tx.getReceipt(client));
console.log("Flora creation complete!");
// Helper function to create topics
async function createTopic(
memo: string,
adminKey: KeyList,
submitKey: KeyList
): Promise<TopicId> {
return new TopicCreateTransaction()
.setAdminKey(adminKey)
.setSubmitKey(submitKey)
.setTopicMemo(memo)
.execute(client)
.then((tx) => tx.getReceipt(client))
.then((receipt) => receipt.topicId!);
}
Additional Implementation Notes:
- Member Discovery: Use HCS-11 profile resolution to retrieve member public keys
- Key Management: Ensure all members securely store their private keys
- Error Handling: Production implementations should handle network failures, insufficient funds, and invalid keys
- Profile Storage: Choose appropriate storage mechanism (HCS-1, IPFS, Arweave) based on requirements
- Activation Monitoring: Implement listeners to track
flora_createdmessages for activation confirmation
Security Considerations
1. Key Reuse Risk
Risk: Members typically reuse their Petal key inside Flora. Compromise of that private key affects all accounts using that key (Base account, Petal account, and all Flora memberships).
Mitigations:
- USE CAUTION when managing private keys
- Utilize hardware wallets (Ledger, Trezor) for key storage
- Implement key rotation policies where possible
- Consider using separate keys for high-value Floras
- Monitor account activity for unauthorized transactions
Impact: Single key compromise can lead to:
- Unauthorized Flora transactions (if attacker gains ≥T keys)
- Theft of assets from Base and Petal accounts
- Reputation damage if malicious actions are taken
2. Threshold Selection
Choosing the right threshold (T) value is critical for balancing security and operational efficiency.
Recommendations:
| Member Count (M) | Recommended Threshold (T) | Rationale |
|---|---|---|
| 2 | 2 | Both members must agree (100% consensus) |
| 3 | 2 | Allows one member to be offline |
| 4 | 3 | Majority + 1, prevents 50/50 deadlock |
| 5-7 | ⌈⅔ M⌉ | Supermajority, balances liveness & safety |
| 8+ | ⌈⅔ M⌉ | Supermajority, ensures strong consensus |
General Rule: For ≤ 4 members, T = M − 1 is RECOMMENDED. For 5+ members, T ≈ ⅔ M balances liveness with safety.
Considerations:
- Too Low: Easier for malicious minority to execute unauthorized transactions
- Too High: Increases risk of operational gridlock if members become unavailable
- Liveness: Consider likelihood of members being offline
- Safety: Consider trust level and potential for collusion
3. Membership Revocation
Removing a malicious or compromised member is itself a multisig transaction requiring ≥T signatures.
Challenges:
- Attacker with T−1 colluding members can block their own removal
- Removal process can be slow if members are unresponsive
- KeyList update requires coordination of honest members
Mitigations:
- Set
membershipChangepolicy to requireT+1signatures where feasible - Implement emergency procedures for rapid member removal
- Maintain off-chain communication channels for crisis coordination
- Consider time-locks on membership changes for additional security
- Require higher threshold for removing founding members
Best Practice: Document clear procedures for handling compromised members, including:
- Detection criteria (suspicious transactions, unresponsive members)
- Emergency contact methods
- Required evidence for removal votes
- Asset protection measures during removal process
4. Data Availability
Risk: Off‑chain storage (IPFS, Arweave, HTTPS) may become unavailable, making Flora metadata inaccessible.
Mitigations:
- Prefer HCS‑1 for critical metadata (guaranteed availability on Hiero)
- For IPFS: Pin files on multiple nodes (your own + pinning services)
- For Arweave: Ensure proper funding for permanent storage
- For HTTPS: Use reliable hosting with backups
- Maintain local copies of all Flora metadata
- Document alternative resolution paths in case of primary storage failure
Availability Guarantees by Storage Type:
| Storage Type | Availability | Permanence | Cost | Recommendation |
|---|---|---|---|---|
| HCS-1 | Very High | Permanent | Low | ✅ Recommended for critical data |
| IPFS | Medium-High | Variable | Very Low | ⚠️ Requires active pinning |
| Arweave | High | Permanent | Medium | ✅ Good for large data |
| HTTPS | Variable | Variable | Low | ❌ Not recommended |
5. Topic Access Control
Risk: Improper topic configuration can lead to unauthorized message submission or topic modification.
Best Practices:
- Admin Key: Always set to Flora's T/M threshold key
- Submit Key: Set to 1/M for routine operations, higher threshold for sensitive topics
- Monitor: Implement automated monitoring for unauthorized topic messages
- HIP-991 Fees: Consider adding custom fees to prevent spam
- Key Updates: Require ≥T signatures for any topic key changes
6. Scheduled Transaction Security
Risk: Malicious members could create scheduled transactions with misleading descriptions in the data field.
Mitigations:
- Always verify scheduled transaction contents on Hiero network before signing
- Don't rely solely on
datafield descriptions - Implement automated transaction analysis tools
- Set expiration times on scheduled transactions (e.g., 7 days)
- Require multiple members to verify high-value transactions
- Use standardized transaction templates for common operations
Verification Checklist:
- Schedule ID matches the one in TTopic message
- Transaction type is as described
- Amounts and recipients are correct
- No unauthorized changes to Flora keys
- Expiration time is reasonable
- Transaction follows Flora policies
Profile Updates
Flora profiles can be updated by:
- Uploading new profile JSON to storage
- Updating Flora account memo to reference new profile
- Posting
state_updateor similar notification to STopic
Backward Compatibility: New profiles SHOULD maintain compatibility with previous versions where possible. Add new fields rather than removing existing ones.