ConceptioArchivearXiv CS
arXiv CSopen access

Data Structures for Private Token Transfers in TEE-Based Networks

Unknown · 2026 · arxiv_cs
arXiv CS · Papers · License: Open Access · 2026
Open Source ↗Direct PDF ↓
cryptography, security, privacy, cybersecurity

Data Structures for Private Token Transfers in TEE-Based Networks Blake Regalia1 and Benjamin Adams2[0000−0002−1657−9809] Solar Republic LLC, USA, [email protected] Department of Computer Science and Software Engineering, University of Canterbury, New Zealand, [email protected] 1

arXiv:2607.04032v1 [cs.CR] 4 Jul 2026

2

Abstract. Trusted execution environment (TEE) based confidential smart contract networks promise privacy but remain vulnerable to storage access pattern attacks that can link senders and recipients in token transfers. When contracts update recipient balances during transfers, the unique storage keys accessed reveal transaction relationships even when data is encrypted. This paper introduces two novel data structures to address this vulnerability: the Delayed Write Buffer (DWB) and the Bitwise-Trie of Bucketed Entries (BTBE). The DWB delays recipient balance updates by buffering pending transfers and randomly settling entries, breaking the direct correlation between transfer execution and recipient storage access. The BTBE further enhances privacy by grouping addresses into constant-sized buckets, preventing flooding attacks and creating anonymity sets for balance queries. Additionally, we present a private notification system enabling real-time, privacy-preserving push notifications for confidential contracts. Our domain-specific approach leverages the unique characteristics of token transfers—asymmetric balance updates and tolerance for delayed settlement—to achieve practical performance with probabilistic anonymity guarantees. Keywords: Private transfer · Smart contract · Trusted execution environment.

1

Introduction

Trusted execution environment (TEE) based confidential smart contract networks have emerged in recent years in recognition of the limitations posed by public blockchain databases [18, 21]. These networks leverage hardware-based isolation to execute smart contract code securely, with the intention that sensitive data remains confidential from external observers and even from the network node operators. Programmable privacy provides application-level privacy, which provides a flexible set of privacy characteristics for users beyond simple transactional privacy [2]. Examples of blockchains that now implement programmable privacy with TEEs include Secret Network, Oasis, and Phala [8, 24, 25]. Beyond these, TEE-based confidential features are increasingly being adopted by other natively public chains. TEE network confidentiality is touted as enabling a number of new types of privacy-preserving financial applications, given that TEEs are

2

B. Regalia and B. Adams

far more efficient than competing privacy technologies such as zero-knowledge proof systems (for two-party interaction) or fully homomorphic encryption. For Secret Network and Oasis, data confidentiality is implemented in the database record through encrypted keys and values. This approach leaves applications such as token contracts susceptible to access-pattern attacks when they are implemented naively, e.g. via a simple translation of the ERC20 standard [10, 15]. When performing token transfers, secret contracts must store balances and transfer histories in their internal (encrypted) key-value databases. However, even though the database key is encrypted, it is unique to the recipient. This allows an attacker to monitor which database keys are read from and written to each execution to deduce storage access patterns and thus correlate transfers to a particular recipient the next time that key is read from or written to. Since the contract must access a sender’s balance when executing an outgoing transfer (to make sure they have enough to cover the spend), this leads to a conundrum: how can we update a recipient’s balance during a transfer without accessing a storage area associated with their account? Jean et al. [15] demonstrated a catastrophic privacy failure that links senders and recipients for token transfers using Secret Network’s SNIP-20 token standard, and they suggested two ways to mitigate the issue. Their first proposed solution was to use decoys, essentially a set of user-supplied mock recipients for a given transaction. This solution was implemented for Secret Network tokens soon after the exploit became known. However, because it relies on user intervention and is applied sparingly and inconsistently by dApps and users, it has largely failed to achieve the desired result. The second proposed solution was to implement an oblivious RAM (ORAM) implementation, either at the network-level, overriding get/set operations for the encrypted database, or within the contract [12]. However, issues around the efficiency and best way to develop that remain to be explored. While the best-known ORAM schemes achieve O(log N ) complexity per access, much of ORAM’s cost comes from bandwidth blowup (reading and writing more data than necessary) potentially gas-prohibitive in a blockchain context [22]. Other solutions that might include off-chain computation require multiple-steps and would not allow transactions to occur per block. In this paper, we present a third, domain-specific option using two new data structure constructions: the Delayed Write Buffer (DWB) and the Bitwise-Trie of Bucketed Entries (BTBE), which provide unlinkability between senders and recipients for token transfers with a low-complexity design that can be implemented within the token contract. In addition, we complement this functionality with a specification for private notifications, enabling immediate, private feedback to recipients of token transfers. While this solution does not have the full generality of ORAM, when tailored to the narrow case of token transfer storage, it has minimal and consistent gas/computation overhead and provides probabilistic anonymity.

Data Structures for Private Token Transfers in TEE-Based Networks

1.1

3

Related work

Oblivious RAM. The concept of Oblivious Random Access Memory (ORAM) was first introduced by Goldreich and Ostrovsky almost 30 years ago as a cryptographic primitive designed to hide memory access patterns from adversaries who can observe which memory locations are accessed during program execution [13]. The fundamental security guarantee of ORAM is that the sequence of memory accesses produced by any two programs with the same running time are computationally indistinguishable to an observer monitoring the physical memory interface. Formally, an ORAM scheme provides oblivious simulation of a program’s memory access pattern. Given a sequence of memory operations (read/write requests to logical addresses), an ORAM construction transforms these into a sequence of physical memory accesses such that the physical access pattern reveals no information about the logical access pattern, beyond the total number of operations performed. This property is crucial in scenarios where an adversary can monitor memory access patterns but cannot observe the actual data being accessed, such as in cloud computing environments or when using untrusted storage systems. Significant advances in ORAM efficiency emerged with tree-based constructions, most notably Path ORAM introduced by Stefanov et al. [22]. Path ORAM organizes data in a binary tree structure where each data block is assigned to a random leaf, and accessing a block requires reading and writing an entire rootto-leaf path. This approach achieves O(log N ) overhead per access while maintaining strong security guarantees through periodic reshuffling of data along accessed paths. Circuit ORAM further optimized tree-based constructions to achieve asymptotically optimal O(log N ) overhead with smaller constants [23]. Traditional ORAM constructions assume that both read and write operations must be performed obliviously. However, many practical applications require only write privacy. Roche et al. introduced deterministic, stash-free writeonly ORAM (WO-ORAM), demonstrating that significant performance improvements are possible when read operations do not require obfuscation [20]. WOORAM constructions typically employ a delayed write strategy where write operations are buffered and processed in batches, rather than immediately updating the target memory location. This approach allows multiple write operations to be combined and randomized before being committed to storage, breaking the correlation between the timing of write requests and physical storage locations. Recognizing that real-world applications often exhibit repeated access patterns to the same memory locations, Dautrich et al. introduced Burst ORAM to minimize response times for such access patterns [9]. Burst ORAM’s batching strategy demonstrates how application-specific optimizations can be incorporated into ORAM designs while maintaining security guarantees. The scheme ensures that an adversary observing the physical access pattern cannot determine whether a given operation resulted from a single logical access or from multiple accumulated accesses to the same location.

4

B. Regalia and B. Adams

Access-pattern and side-channel vulnerabilities. The importance of hiding storage access patterns extends beyond traditional memory systems to encrypted databases and distributed storage systems. Islam et al. demonstrated that even when database contents are encrypted, access pattern leakage can compromise user privacy by revealing which records are being queried [14]. Their work showed that statistical analysis of access patterns can lead to significant information leakage, even in the absence of plaintext data. This analysis is particularly relevant to programmable privacy blockchain systems, where transaction data may be encrypted but storage access patterns during smart contract execution can reveal information about user interactions. The challenge is compounded in blockchain systems because the execution environment may be partially trusted or controlled by potentially malicious node operators. The effectiveness of privacy-preserving storage systems depends on their resistance to side-channel attacks, particularly timing-based attacks that can reveal information about internal system state. Kocher et al. demonstrated that variations in execution time can leak cryptographic secrets, establishing the importance of constant-time algorithm design [16]. Similarly, Bernstein showed how cache timing variations can compromise the security of cryptographic implementations [3]. 1.2

Contribution

While existing ORAM constructions provide strong theoretical foundations, their direct application to blockchain token transfers presents significant efficiency and practicality challenges. Traditional ORAM schemes are designed for generalpurpose memory access patterns and do not exploit the specific characteristics of token transfer operations, such as the asymmetric nature of balance updates (one decrease, one increase per transfer) and the tolerance for delayed settlement of incoming transfers. Furthermore, existing approaches do not address the unique attack vectors present in blockchain systems, such as flush attacks where adversaries can manipulate buffer contents through coordinated transactions, or the need to maintain identical gas consumption patterns across different execution paths to prevent side-channel leakage. The domain-specific nature of token transfers enables several novel optimizations not possible in general ORAM constructions. First, the unidirectional flow of value allows for asymmetric treatment of sender and recipient operations. Senders must be processed immediately for balance verification, while recipients can tolerate delayed processing through buffering mechanisms. Second, the append-only nature of transaction histories permits the use of linked-list accumulation strategies that eliminate the need for complex data reshuffling while maintaining privacy guarantees. Third, the finite and predictable set of operations (balance queries, transfers, and history queries) allows for specialized constant-time algorithms that are more efficient than general-purpose oblivious data structures. These domain-specific insights enable a hybrid approach that combines write-only ORAM buffering with tree-based bucketing and novel anti-flush mechanisms, achieving practical performance.

Data Structures for Private Token Transfers in TEE-Based Networks

2

5

Requirements

To address the challenges identified, we articulate a set of design goals and security properties. These capture the constraints under which the system must operate and the guarantees it must provide. This approach allows us to iteratively specify necessary components, avoid redundancies, and ensure that solutions do not conflict with one another. R1. Storage Access Patterns ⇒ Transfers Table Property: Transfers must not produce correlated storage access patterns linking sender and recipient. Mechanism: Instead of writing to the recipient’s storage directly, write pending transfers to a table that gets fully read and overwritten on each execution. R2. Finite Table Capacity ⇒ Delayed Write Buffer Property: The transfer table has finite capacity; when full, it must be updated without leaking information about which entries are evicted. Mechanism: Randomly select an entry from the table (that is, the buffer) to evict and update the stored balance of its recipient (i.e., “settle” the entry). R3. Flush Attacks ⇒ Accumulation Property: Repeated transfers to the same recipient must not reduce the anonymity set or reveal prior recipients through forced settlement, as this would allow an attacker to “flush” the rest of the buffer and record which keys are accessed. Mechanism: Transfers to recipients who have an existing entry accumulate in place rather than creating new ones or settling and replacing existing ones. R4. Side Channel Leaks ⇒ Constant Time Operations Property: Execution time, storage access timing, and gas usage must remain consistent and independent of buffer state, preventing leakage to a malicious observer. Mechanism: All operations before the final storage read are constant-time, independent of transfer parameters. R5. Storage Write Leaks ⇒ Phony Writes R5a. Recipient Entry Property: Due to the Accumulation mechanism in R3, a random entry does not need to be evicted if the transfer recipient already has an entry. However, this would lead to a branch in execution where sometimes an entry gets settled and sometimes not. More importantly, the absence of a write would leak that the recipient of the transfer was already in the buffer. Mechanism: If the recipient is already in the buffer, rather than settling their existing entry, perform a phony write to an unrelated address’s storage location.

6

B. Regalia and B. Adams

R5b. Owner/Sender Balance Property: Outgoing transfers may exceed the value of an owner’s stored balance, but not when combined with the cumulative sum of their incoming transfer entries in the buffer (that is, their total balance). Checking and updating an owner’s total balance must not reveal whether they had an entry in the buffer. Mechanism: The contract always checks and settles the owner’s buffer entry if it exists. If the owner does not have an entry in the buffer, in order to produce the same storage write pattern, it performs a phony write to the storage area of an unrelated address. R6. Flooding Attacks ⇒ Buckets Property: A vigilant attacker with endless funds must not be able to deduce the entries in the buffer through a series of sandwiched flooding attacks. By monopolizing the buffer with transfers to known recipients, an attacker may establish a high degree of certainty over the buffer’s contents. Albeit prohibitively expensive to perform at scale, a determined attacker may be able to correlate or de-anonymize an individual transfer event to a pre-selected victim recipient. Mechanism: Instead of storing each owner’s/sender’s/recipient’s balance and history under a single storage key, balances and histories are grouped into buckets of finite anonymity sets. Reads and writes occur at the bucket level, concealing individual access.

3

Delayed Write Buffer (DWB)

We introduce the Delayed Write Buffer (DWB), a domain-specific fixed-width data structure that gets fully read and overwritten on every transfer execution. A token contract requires only a single DWB instance to handle all token transfers. DWB contents are encrypted at rest in the contract’s key-value store by virtue of the confidential contract platform, where it is stored under a constant storage key. In naive implementations, the storage key associated with a recipient’s balance is accessed during transfer executions to update their balance, revealing storage access patterns. With the DWB, instead of accessing any storage areas associated with the recipient, an entry containing the recipient’s address, pending token amount, and a pointer to a linked list of transfer events is inserted into the DWB. A transfer event contains metadata such as the sender’s address, date time, and an optional memo. Once the DWB has reached saturation, that is, every slot in its fixed-width capacity is occupied by an entry, the contract selects an entry from the buffer at random to “settle” in order to make room for the new entry. In order to prevent an attacker from deducing which entry was settled, the source of randomness must be private. In our implementation, randomness is provided by Secret VRF which uses the network’s internal private key to derive a unique secure seed for RNG on every contract execution within the TEE. Settling an entry updates the associated recipient’s stored balance and removes the entry from the buffer. This mechanism artificially delays the even-

Data Structures for Private Token Transfers in TEE-Based Networks

7

tual write to a recipient’s storage area by some random number of executions, avoiding direct storage access association between sender and recipient. 3.1

Executing the transfer

Here we describe an example (illustrated in Figure 1) of executing a transfer transaction using a DWB.

Fig. 1. An example transaction using a DWB, showing the order of read/write storage access operations. Notice how Bob’s entry was randomly selected from the buffer to be settled in order to insert the new entry for Carol.

First, a new transfer event is saved to storage, keyed by a globally unique transfer event ID. Next, the contract loads the entire DWB from storage, selects an entry at random, and settles it. At this point in the example process, nothing associated with the recipient’s storage areas has been accessed. Instead, the sender of the transaction has incidentally updated the stored balance of a random account that was designated by an entry in the DWB, even though the transaction sender and the accessed account likely have no affiliation. This strategy greatly reduces the ability for an attacker to correlate sender and recipient through storage access patterns. 3.2

Querying for balance and history

Entries stored in the DWB count towards a user’s total balance. When Carol queries for her balance, the contract must search the DWB to find any entries where Carol is the recipient. It adds this value to her stored balance to arrive at her actual total balance. Queries for holistic transfer history must also access data from both storage areas (more on history below).

8

B. Regalia and B. Adams

Our approach does not guarantee privacy during query operations. As opposed to transactions which are broadcasted to the entire network, queries are ostensibly private between the client and the node serving their RPC call. While the node cannot decrypt the query nor its outputs, and its execution is run within the TEE, a malicious node operator can monitor which storage keys are accessed from outside the enclave. For example, a victim repeatedly querying for their balance may reveal their balance storage key. If the victim also broadcasts transaction requests to the node, the attacker may be able to infer the client’s account address and by extension their balance storage key. However, this information is less meaningful in practice when the DWB is used since each transfer execution does not access the recipient’s balance storage key, leaving an attacker with a large anonymity set of potential senders to correlate with a given recipient. Additionally, as explained in Section 4, a complementary data structure for stored balances further mitigates against these types of attacks by creating anonymity sets for stored balances.

3.3

Owner’s balance

Executing a transfer requires a balance check of the owners’s3 account. Since a transfer must decrease the owner’s total balance, the contract first settles any pending entries in the DWB designated for their account. In order to prevent leaking information about DWB contents, the owner’s balance is overwritten regardless of whether or not such an entry is found. This action produces a definite storage access signal at the owner’s stored balance key, establishing a likely association between the public message sender and the private account owner’s storage area. However, as mentioned in Section 3.2, this information is less meaningful to an attacker in practice, and is rendered even less so with the addition of the complementary data structure introduced in Section 4.

3.4

Distinct recipients

A nontrivial privacy vulnerability arises when recipients are allowed to appear multiple times in the DWB. An attacker can flush access to a victim’s stored balance by executing many simultaneous transfers to them. Effectively, this would create a high probability that every entry in the DWB is designated to the victim, and would eventually reveal repeated access to the same storage key. To mitigate this, our implementation enforces that entries in the DWB are distinct by recipient address, and repeated transfers to the same recipient accumulate in the existing entry. In other words, if the recipient already has an entry designated to them in the DWB, the contract updates this entry with the cumulative transfer amount rather than inserting a new entry. 3

The term owner is used to distinguish the holder of funds from the message sender, who may be executing on the owner’s behalf via permissioned allowance.

Data Structures for Private Token Transfers in TEE-Based Networks

3.5

9

Transaction history events

Accumulating transfers in the DWB presents a challenge to storing historical records. In classic Secret tokens, users have the ability to query for their transaction history which includes all outgoing and incoming transfers. If the contract were to simply write each historical record to a storage area associated with the recipient, it would produce a storage access pattern and defeat the purpose of the DWB. Instead, each transfer event is appended to a global list and a reference to its ID is saved under a field in the DWB entry. Since repeated transfers to a given recipient accumulate in the DWB, the entry needs a way to store multiple events. Our solution is to use a linked list, where each new transfer inserts at the head of the list as shown in Figure 2.

Fig. 2. Repeated transfers to the same recipient accumulate in a linked list of transaction events per DWB entry. Notice how insertions do not dereference previous items in the list. Thus, updating the list does not produce storage access patterns.

With this approach, an entry in the DWB can accumulate events ad infinitum. The storage areas associated with transaction history events are only ever accessed a single time across all executions (when they are written to). The only other time they are dereferenced is when they are read by the query node during private user queries for their transaction history. 3.6

Saturation

The DWB privacy mechanism relies on settling authentic entries to the storage area. During the first k interactions, the DWB has empty slots that would not produce the desired storage access effects if settled, due to the lower anonymity set size. Therefore, DWB privacy is most effective once it is fully saturated. Our implementation tracks the saturation of the DWB during these initial executions and refrains from settling entries until it reaches full saturation. 3.7

Data structure example for token transfers

The DWB is a simple byte sequence of k entries, concatenated with a single uint<log2 (k)> which counts down the unused capacity while under-saturated.

10

B. Regalia and B. Adams

Each entry consists of the recipient, amount, a pointer to the head of the events linked list, and the current length of the list. 20 bytes: recipient (canonical address) +8 bytes: amount (uint64) +5 bytes: events list ID (fits in uint64) +2 bytes: list length --------------------= 35 bytes per entry

3.8

Constant time search

All operations prior to the final storage area write must run in constant time in order to prevent leaking information about branch conditions through side channels. This includes byte slice comparisons and the algorithm used to search for a matching owner address in the DWB during the transfer process. To give an example without constant time search, and assuming the entries were sorted by address, a hypothetical attack could brute force crafted addresses that probe insertion timing and use a binary search strategy to deduce the leading bytes of an address belonging to an entry in the DWB. 3.9

Selecting buffer parameters

Let k be the capacity of the buffer. The probability that an entry for a given recipient has settled and thus accessed their stored balance after n subsequent transfer executions is given by:  n k−1 P (transfer settling) = 1 − k We visualize this formula for various values of k in Figure 3. Interpreting the diagram, for k = 64, we see an 80% chance that an entry has settled after 100 executions. This uncertainty is what prevents an attacker from identifying which recent transaction actually transferred tokens to a given recipient. Another way to interpret this formula is to answer at what point an attacker reaches high confidence that a victim’s stored balance area was accessed within the last n executions. In other words, for a buffer width of k = 64, reaching a 99.5% confidence threshold is roughly equivalent to an anonymity set of size 336.  n 64 − 1 P (transfer settling) = 1 − = 0.995 64 n=

ln(0.005) = 336.4362... ln(63/64)

In physics, a 5σ threshold (5 standard deviations) is used as a statistical significance measure to indicate that an observed effect departs from the null hypothesis, which corresponds to a confidence level of 99.99994%. Reaching this confidence level for k = 64 would be equivalent to an anonymity set of size 909.

Data Structures for Private Token Transfers in TEE-Based Networks

11

Fig. 3. Probability a transfer has settled, and thus the recipient’s storage area has been accessed, after n subsequent transfer executions.

4

Bitwise-Trie of Bucketed Entries (BTBE)

We introduce a secondary data structure to improve the privacy of accessing users’ stored balances during token transfers, complementing the benefits described above from the DWB. The Bitwise-Trie of Bucketed Entries (BTBE) manages a tree of constant-size tables which deterministically groups items by the leading bits of the cryptographic hash of their account address, better known as buckets [19]. Grouping multiple records into a bucket creates a finite open anonymity set that limits the granularity of storage access patterns. To preserve privacy, the hash is derived using a secret key internal to the contract. The value of any bucket item stores the user’s balance and transfer history. Since the buckets have fixed capacity, new buckets must be created and existing ones must occasionally be rebalanced on insertion. The bitwise-trie component of the data structure enables efficient access to buckets, ensuring that the query and execution cost of locating and inserting entries grows logarithmically with new recipients. The height of the trie corresponds with the ith leading bit of the hash. The diagram shown in Figure 4 illustrates the insertion of a new entry which requires rebalancing the trie. The example inserts an entry for Edgar’s stored balance. His address hashes to the hexadecimal value 0x75 (0111 0101). Notice how the trie changes as new branches are created until reaching the 2nd leading bit of the hash, where Edgar’s entry eventually finds capacity in Bucket #2.

12

B. Regalia and B. Adams

Fig. 4. Example of inserting a new entry in the BTBE. 1. Bucket #0 is full, resulting in a leaf node split. 2. The inserted entry’s hash routes it to Bucket #0, which is again full, resulting in another leaf node split. 3. The inserted entry’s hash routes it to Bucket #2, which has capacity and accepts the entry, terminating the insertion process.

5

Private notifications

Observing state changes to the encrypted databases of confidential smart contracts that affect an interested user is more difficult than the equivalent in a public blockchain. Wallets and dApps currently resort to a polling-based approach in order to notice changes to a user’s private state within a contract. For example, a dApp might periodically query a set of token contracts to discover a new incoming transfer. However, this approach of querying contracts every so often is inefficient and can create unwanted load on query nodes. Additionally, there is no clear best practice for determining an optimal polling rate. Here, we describe a specification that addresses these limitations by introducing a privacy-preserving push notification system for confidential smart contracts on Secret Network. The system enables clients to receive real-time notifications for specific events while maintaining complete privacy of recipient and contents. This approach leverages the existing Tendermint event infrastructure combined with cryptographic techniques to create globally unique notification identifiers only decipherable by the intended recipients. Tendermint, the consensus engine for Secret Network, includes a publishsubscribe event stack that allows nodes to transmit network events directly to subscribed clients [11]. It does so using JSONRPC over WebSockets [7]. Contracts are able to emit arbitrary plaintext data into an event log which gets broadcast by the aforementioned stack. 5.1

Notification Framework

The notification system operates on several key principles. Smart contracts generate globally unique, single-use notification identifiers using cryptographic hash

Data Structures for Private Token Transfers in TEE-Based Networks

13

functions. These identifiers serve as attribute keys in transaction logs, creating a discrete signaling mechanism visible only to intended recipients. The system distinguishes between different event types through channels, allowing contracts to separate notifications for transfers, messages, gaming events, and other application-specific activities. The architecture relies on shared secrets between clients and contracts, termed notification seeds. These seeds serve as cryptographic key material to generate notification identifiers. Contracts derive default seeds using an internal secret combined with recipient addresses, enabling clients to obtain notification identifiers without executing transactions. For enhanced security, clients can establish custom seeds through cryptographic signatures. 5.2

Channel Operating Modes

The system supports three distinct operating modes, each optimized for different use cases and security requirements. Counter Mode provides the most convenient client experience by using sequential counters to generate unique notification identifiers. Clients need only recompute identifiers when receiving notifications and can search transaction history for missed events. TxHash Mode eliminates side-channel vulnerabilities by incorporating transaction hashes into identifier generation. This approach provides stronger security guarantees but requires clients to recompute identifiers for every contract execution, increasing computational overhead. Bloom Mode enables efficient notification delivery to multiple recipients simultaneously. It uses Bloom filters, probabilistic data structures that encode set membership with controlled false positive rates to indicate which recipients should check for notifications [5]. The system employs constant-size filters with configurable parameters to balance efficiency and privacy requirements. 5.3

Information Hiding Techniques

The system employs multiple layers of privacy protection to prevent information leakage. Notification data encryption uses the ChaCha20-Poly1305 authenticated encryption algorithm, chosen for its efficiency in constrained blockchain environments and widespread implementation support [4]. To prevent traffic analysis attacks, contracts implement two critical privacy measures. First, all notification data is padded to constant lengths within each channel, preventing observers from inferring message content based on size variations. Second, contracts emit consistent numbers of log attributes regardless of actual notification activity, using decoy notifications to mask genuine events. 5.4

Cryptographic Security Model

The security model relies on established cryptographic primitives. HKDF (HMACbased Key Derivation Function) generates deterministic yet unpredictable seeds

14

B. Regalia and B. Adams

from contract internal secrets and recipient addresses [17]. HMAC-SHA256 produces notification identifiers that appear random to external observers but remain deterministic for authorized parties [1]. The secp256k1 elliptic curve signature scheme enables clients to establish custom shared secrets through cryptographic proof of key ownership [6]. The security model relies on standard cryptographic assumptions including the discrete logarithm problem’s hardness in secp256k1, HMAC-SHA256’s pseudorandomness properties, and ChaCha20Poly1305’s semantic security [1, 6, 4]. These assumptions align with widely-used blockchain security models and benefit from extensive cryptographic analysis. 5.5

Threat Model Considerations

Counter Mode exposes a potential privacy vulnerability in which a malicious query node might associate a notification ID filter with a user’s IP address. TxHash Mode eliminates this attack vector, though at the cost of increased client complexity. The system’s privacy guarantees depend on proper implementation of constant-time operations and consistent event emission patterns. Contracts that fail to maintain consistent log sizes or data padding may leak information about notification patterns or recipient identities through traffic analysis. For multi-recipient channels, proper Bloom filter parameter selection critically affects both efficiency and privacy. The filter size (m), hash function count (k), and underlying hash function (h) must be chosen based on expected recipient group sizes and acceptable false positive rates. The specification recommends cryptographically secure hash functions to prevent preimage attacks while ensuring uniform distribution for filter effectiveness.

6

Results and Discussion

To evaluate our approach, we implemented a full reference implementation of a token contract on Secret Network incorporating the Delayed Write Buffer (DWB), the Bitwise-Trie of Bucketed Entries (BTBE), and the private notification system. The codebase is available for review here: https://anonymous.4open.science/r/snip20-reference-impl-F846/README.md. 6.1

Deployment and Adoption

Our contract maintains the same Secret token interface for queries and executions, ensuring backwards compatibility with existing dApps. Since upgrading a live contract’s database schema is costly and complicated, we implemented a lazy migration mechanism for legacy balances. This enabled the community to upgrade major bridged assets (USDC, USDT, BTC, ETH, and sSCRT) to our privacy-preserving design. In total, 42 mainnet Secret tokens were upgraded, securing over USD 10 million.

Data Structures for Private Token Transfers in TEE-Based Networks

6.2

15

Gas and Execution Overheads

We benchmarked the contract under a variety of workloads to measure execution overhead relative to the naive token contract baselines. The results show that: (1) The DWB incurs a fixed gas overhead proportional to the buffer width k during transfer executions; (2) The BTBE incurs a variable gas overhead proportional to the height of the trie and size of the bucket; and (3) The notifications add a relative small fixed gas overhead to each execution thanks in part to the lightweight encryption algorithm ChaCha20-Poly1305. In the worst case observed, gas usage increased by 26% compared to the baseline SNIP-20 token. We consider this a modest tradeoff for the privacy protections gained.

6.3

Privacy Guarantees in Practice

Our experiments demonstrate that the DWB effectively decouples sender and recipient storage accesses. With a buffer capacity of k = 64, an attacker would require nearly 300 subsequent transactions to achieve even a 99% confidence that a victim’s balance has been accessed by one of those transfers. This simulates a large anonymity set for each recipient using only a fraction of the equivalent space, and substantially improves the privacy compared to naive contracts where association between sender and recipient are immediate due to direct storage access. Additionally, the BTBE further obfuscates storage access patterns for user balances by grouping balances into buckets of constant size.

6.4

Private Notifications

The push-based notification system demonstrates significant improvements over polling. Clients receive real-time transfer alerts without exposing recipient identity or event timing to the network. In particular, the Bloom filter mode provides efficient multi-recipient signaling with false positive rates kept below 1% under practical configurations. While TxHash mode increases client computation, it effectively mitigates side-channel risks, providing a tunable tradeoff between security and efficiency.

6.5

Limitations and Future Work

Our approach does not eliminate all forms of leakage. Query-based attacks remain a partial vector, since repeated balance queries by a malicious node operator can still reveal a user’s balance storage key. Similarly, DWB anonymity sets depend on transaction volume; during low-activity periods, settlement intervals shrink and anonymity guarantees weaken. Future work may explore adaptive buffer resizing, integration with network-level ORAM, and hybrid models that combine DWB/BTBE with zk-SNARK-based auditing for stronger guarantees.

16

B. Regalia and B. Adams

References 1. Bellare, M., Canetti, R., Krawczyk, H.: Keying hash functions for message authentication. In: Annual international cryptology conference. pp. 1–15. Springer (1996) 2. Benarroch, D., Gillespie, B., Lai, Y.T., Miller, A.: SoK: Programmable privacy in distributed systems. Cryptology ePrint Archive (2024) 3. Bernstein, D.J.: Cache-timing attacks on AES (2005), retrieved from https://paperhub.s3.amazonaws.com/4089cd9ff9eb1087b12e16977d4c2ac0.pdf 4. Bernstein, D.J.: The poly1305-aes message-authentication code. In: International workshop on fast software encryption. pp. 32–49. Springer (2005) 5. Bloom, B.H.: Space/time trade-offs in hash coding with allowable errors. Communications of the ACM 13(7), 422–426 (1970) 6. Brown, D.R.L.: SEC 2: Recommended elliptic curve domain parameters (2010), https://www.secg.org/sec2-v2.pdf 7. Buchman, E.: Tendermint: Byzantine fault tolerance in the age of blockchains. Ph.D. thesis, University of Guelph (2016) 8. Cheng, R., Zhang, F., Kos, J., He, W., Hynes, N., Johnson, N., Juels, A., Miller, A., Song, D.: Ekiden: A platform for confidentiality-preserving, trustworthy, and performant smart contract execution. arXiv preprint arXiv:1804.05141 (2018) 9. Dautrich, J., Stefanov, E., Shi, E.: Burst ORAM: Minimizing ORAM response times for bursty access patterns. In: 23rd USENIX Security Symposium (USENIX Security 14). pp. 749–764 (2014) 10. Desai, H., Kantarcioglu, M.: Secauctee: securing auction smart contracts using trusted execution environments. In: 2021 IEEE international conference on blockchain (blockchain). pp. 448–455. IEEE (2021) 11. Eugster, P.T., Felber, P.A., Guerraoui, R., Kermarrec, A.M.: The many faces of publish/subscribe. ACM computing surveys (CSUR) 35(2), 114–131 (2003) 12. Goldreich, O.: Towards a theory of software protection and simulation by oblivious RAMs. In: Proceedings of the nineteenth annual ACM symposium on Theory of computing. pp. 182–194 (1987) 13. Goldreich, O., Ostrovsky, R.: Software protection and simulation on oblivious RAMs. Journal of the ACM (JACM) 43(3), 431–473 (1996) 14. Islam, M.S., Kuzu, M., Kantarcioglu, M.: Access pattern disclosure on searchable encryption: Ramification, attack and mitigation. In: Network and Distributed System Security (NDSS) Symposium. vol. 20, p. 12 (2012) 15. Jean-Louis, N., Li, Y., Ji, Y., Malvai, H., Yurek, T., Bellemare, S., Miller, A.: SGXonerated: Finding (and partially fixing) privacy flaws in TEE-based smart contract platforms without breaking the TEE. Proceedings on Privacy Enhancing Technologies 2024, 617–634 (2024). https://doi.org/10.56553/popets-2024-0035 16. Kocher, P., Jaffe, J., Jun, B.: Differential power analysis. In: Annual international cryptology conference. pp. 388–397. Springer (1999) 17. Krawczyk, H.: Cryptographic extraction and key derivation: The hkdf scheme. In: Annual Cryptology Conference. pp. 631–648. Springer (2010) 18. Li, R., Wang, Q., Wang, Q., Galindo, D., Ryan, M.: SoK: TEE-assisted confidential smart contract. Proceedings on Privacy Enhancing Technologies 3, 711–731 (2022) 19. Morrison, D.R.: PATRICIA-practical algorithm to retrieve information coded in alphanumeric. Journal of the ACM (JACM) 15(4), 514–534 (1968) 20. Roche, D.S., Aviv, A., Choi, S.G., Mayberry, T.: Deterministic, stash-free writeonly ORAM. In: Proceedings of the 2017 ACM SIGSAC Conference on Computer and Communications Security. pp. 507–521 (2017)

Data Structures for Private Token Transfers in TEE-Based Networks

17

21. Smart, N.: Computing on encrypted data. IEEE Security & Privacy 21(4), 94–98 (2023) 22. Stefanov, E., van Dijk, M., Shi, E., Fletcher, C., Ren, L., Yu, X., Devadas, S.: Path ORAM: an extremely simple oblivious RAM protocol. In: Proceedings of the 2013 ACM SIGSAC conference on Computer & communications security. pp. 299–310 (2013) 23. Wang, X., Chan, H., Shi, E.: Circuit oram: On tightness of the goldreich-ostrovsky lower bound. In: Proceedings of the 22nd ACM SIGSAC Conference on Computer and Communications Security. pp. 850–861 (2015) 24. Woetzel, C.: Secret network: A privacy-preserving secret contract & decentralized application platform (2021), https://www.cryptowhitepapersonline.com/wpcontent/uploads/2023/08/secret.pdf 25. Yin, H., Zhou, S., Jiang, J.: Phala network: A confidential smart contract network based on polkadot. Phala Network (2019)

A

Private notification algorithms

A.1

Contract internal secret derivation

Contract initialization must establish an internal secret with high entropy, unknown to all parties including contract administrators. fun initializeContract(msg, env) { // gather entropy from sender let userEntropy := msg.entropy // extend entropy with environmental information let entropy := concat( env.blockHeight, env.blockTime, env.senderAddress, userEntropy ) // the crux: obtain a unique, cryptographically-strong random value // associated with this execution let seed := env.random() // very important: derive the contract’s internal secret using HKDF let internalSecret := hkdf_sha256( ikm=seed, salt=sha256(entropy), info="contract_internal_secret", length=32 ) // save to storage

18

B. Regalia and B. Adams saveInternalSecretToStorage(internalSecret); // ...

}

A.2

Notification seed algorithm

Contracts derive per-recipient seeds using either custom shared secrets or deterministic generation from the internal secret. fun getSeedFor(recipientAddr) { // recipient has a shared secret with contract let seed := sharedSecretsTable[recipientAddr] // no explicit shared secret; derive seed using contract’s secret if NOT exists(seed): seed := hkdf_sha256( ikm=contractInternalSecret, info=canonical(recipientAddr) ) return seed }

A.3

Notification ID generation

fun notificationIdFor(contractOrRecipientAddr, channelId, env) { let salt := nil // depending on which mode the channel operates in if inCounterMode(channelId): // counter reflects the nth notification for the given // contract/recipient in the given channel let counter := getCounterFor(contractOrRecipientAddr, channelId) salt := uintToDecimalString(counter) // otherwise, channel is in TxHash Mode or Bloom Mode else: salt := env.txHash // compute notification ID for this event let seed := getSeedFor(contractOrRecipientAddr) let material := concatStrings(channelId, ":", salt) let notificationId := hmac_sha256( key=seed,

Data Structures for Private Token Transfers in TEE-Based Networks

19

message=utf8ToBytes(material) ) return notificationId }

A.4

Data Encryption and Decryption

Pseudocode for encrypting data into single-recipient notifications (contract) and decrypting data from single-recipient notifications (client). fun encryptNotificationData( recipientAddr, channelId, plaintext, env ) { // ChaCha20 expects a 96-bit (12 bytes) nonce, so // combine two 12 byte buffers to create nonce let saltBytes := nil // depending on which mode the channel operates in if inCounterMode(channelId): // counter reflects the nth notification for the given recipient // in the given channel let counter := getCounterFor(recipientAddr, channelId) // encode uint64 counter in BE and left-pad with 4 bytes of 0x00 // to make 12 bytes saltBytes := concat(zeros(4), uint64BigEndian(counter)) // otherwise, channel is in TxHash Mode else: // take first 12 bytes of tx hash (make sure to decode the hex string) saltBytes := slice(hexToBytes(env.txHash), 0, 12) // take the first 12 bytes of the channel id’s sha256 hash let channelIdBytes := slice(sha256(utf8ToBytes(channelId)), 0, 12) // produce the nonce by XOR’ing the two previous 12-byte results let nonce := xorBytes(channelIdBytes, saltBytes) // right-pad the plaintext with 0x00 bytes until it is of the desired // length (keep in mind, payload adds 16 bytes for tag) let message := concat(plaintext, zeros(DATA_LEN - len(plaintext)))

20

B. Regalia and B. Adams // construct the additional authenticated data let aad := concatStrings(env.blockHeight, ":", env.txHash) // encrypt notification data for this event let seed := getSeedFor(recipientAddr) let [ciphertext, tag] := chacha20poly1305_encrypt( key=seed, nonce=nonce, message=message, aad=aad ) // concatenate ciphertext and 16 bytes of tag // (note: crypto libs typically default to doing it this way in ‘seal‘) let payload := concat(ciphertext, tag) return payload

} fun decryptNotificationData(contractAddr, channelId, payload, env) { // depending on which mode the channel operates in if inCounterMode(channelId): // counter reflects the nth notification for the given recipient // in the given channel let counter := getCounterFor(recipientAddr, channelId) // encode uint64 counter in BE and left-pad with 4 bytes of 0x00 // to make 12 bytes saltBytes := concat(zeros(4), uint64BigEndian(counter)) // otherwise, channel is in TxHash Mode else: // take first 12 bytes of tx hash (make sure to decode the hex string) saltBytes := slice(hexToBytes(env.txHash), 0, 12) // ChaCha20 expects a 96-bit (12 bytes) nonce // take the first 12 bytes of the channel id’s sha256 hash let channelIdBytes := slice(sha256(utf8ToBytes(channelId)), 0, 12) // produce the nonce by XOR’ing the two previous 12-byte results let nonce := xorBytes(channelIdBytes, counterBytes) // construct the additional authenticated data let aad := concatStrings(env.blockHeight, ":", env.txHash) // split payload

Data Structures for Private Token Transfers in TEE-Based Networks let ciphertext := slice(payload, 0, len(payload) - 16) let tag := slice(payload, len(ciphertext)) // decrypt notification data let seed := getSeedFor(contractAddr) let message := chacha20poly1305_decrypt( key=seed, nonce=nonce, message=ciphertext, tag=tag, aad=aad ) // do not trim trailing zeros because there is no END marker in CBOR. // just decode plaintext as-is let plaintext := message return plaintext }

21

Record · ID 343395 · SHA-256 e1caaa4707f4447d
Retrieved via Conceptio — every document is proof-bundled with source, license, and retrieval metadata.